mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-01-23 02:34:42 +00:00
Make executables ready for static linking (#307)
* Disable CGO (C libs) for coordinator Needed for static linking. * Fix "error strings should not be capitalized (ST1005)" * Fix SA1015 Using time.Tick leaks the underlying ticker, consider using it only in endless functions, tests and the main package, and use time.NewTicker here (SA1015) * Fix SA9004 Only the first constant in this group has an explicit type (SA9004). * Remove unused code in the webrtc package * Fix S1000 Should use a simple channel send/receive instead of select with a single case (S1000). * Force dir creation/check for core downloader * Update Makefile release script * Disable ASLR for worker builds * Remove WORKER_BUILD_PARAMS flag from the CI * Don't force recompilation in release * Add Debian packages installer script * Build worker app without libopusfile * Test worker app without libopusfile * Add opus wrapper without opusfile * Make install.sh executable * Add opus lib in Win builds * Make insecure HTTPS requests when downloading libs * Add ca-certificates for Docker build stage go mod download works only with SSL certificates installed. * Move libx264 wrapper into the repo That way we can get rid of a lot of not needed external Go dependencies. * Update the dependencies
This commit is contained in:
parent
d778a7e084
commit
602b9ea47c
20 changed files with 1278 additions and 212 deletions
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
|
|
@ -33,12 +33,12 @@ jobs:
|
|||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y make pkg-config libvpx-dev libx264-dev libopus-dev libopusfile-dev libsdl2-dev libgl1-mesa-glx
|
||||
sudo apt-get install -y make pkg-config libvpx-dev libx264-dev libopus-dev libsdl2-dev libgl1-mesa-glx
|
||||
|
||||
- name: Get MacOS dev libraries and tools
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: |
|
||||
brew install pkg-config libvpx x264 opus opusfile sdl2
|
||||
brew install pkg-config libvpx x264 opus sdl2
|
||||
|
||||
- name: Get Windows dev libraries and tools
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
|
@ -52,8 +52,8 @@ jobs:
|
|||
mingw-w64-x86_64-pkg-config
|
||||
mingw-w64-x86_64-dlfcn
|
||||
mingw-w64-x86_64-libvpx
|
||||
mingw-w64-x86_64-opus
|
||||
mingw-w64-x86_64-x264-git
|
||||
mingw-w64-x86_64-opusfile
|
||||
mingw-w64-x86_64-SDL2
|
||||
|
||||
- name: Get Windows OpenGL drivers
|
||||
|
|
@ -77,7 +77,7 @@ jobs:
|
|||
if: matrix.step == 'build' && matrix.os == 'windows-latest'
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
make WORKER_BUILD_PARAMS=-buildmode=exe build
|
||||
make build
|
||||
|
||||
- name: Build Linux app
|
||||
if: matrix.step == 'build' && matrix.os == 'ubuntu-latest'
|
||||
|
|
@ -95,19 +95,19 @@ jobs:
|
|||
env:
|
||||
MESA_GL_VERSION_OVERRIDE: 3.3COMPAT
|
||||
run: |
|
||||
go test -run TestAllEmulatorRooms ./pkg/worker/room -v -renderFrames -autoGlContext -outputPath "../../../_rendered"
|
||||
GL_CTX=-autoGlContext make verify-cores
|
||||
|
||||
- name: Verify core rendering (ubuntu-latest)
|
||||
if: matrix.step == 'check' && matrix.os == 'ubuntu-latest' && always()
|
||||
env:
|
||||
MESA_GL_VERSION_OVERRIDE: 3.3COMPAT
|
||||
run: |
|
||||
xvfb-run --auto-servernum go test -run TestAllEmulatorRooms ./pkg/worker/room -v -renderFrames -autoGlContext -outputPath "../../../_rendered"
|
||||
GL_CTX=-autoGlContext xvfb-run --auto-servernum make verify-cores
|
||||
|
||||
- name: Verify core rendering (macos-latest)
|
||||
if: matrix.step == 'check' && matrix.os == 'macos-latest' && always()
|
||||
run: |
|
||||
go test -run TestAllEmulatorRooms ./pkg/worker/room -v -renderFrames -outputPath "../../../_rendered"
|
||||
make verify-cores
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: matrix.step == 'check' && always()
|
||||
|
|
|
|||
31
Dockerfile
vendored
31
Dockerfile
vendored
|
|
@ -9,32 +9,32 @@ WORKDIR ${BUILD_PATH}
|
|||
# system libs layer
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
gcc \
|
||||
ca-certificates \
|
||||
libopus-dev \
|
||||
libsdl2-dev \
|
||||
libvpx-dev \
|
||||
libx264-dev \
|
||||
make \
|
||||
pkg-config \
|
||||
wget \
|
||||
ca-certificates \
|
||||
libvpx-dev \
|
||||
libx264-dev \
|
||||
libopus-dev \
|
||||
libopusfile-dev \
|
||||
libsdl2-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# go setup layer
|
||||
ARG GO=go1.16.2.linux-amd64.tar.gz
|
||||
ARG GO=go1.16.3.linux-amd64.tar.gz
|
||||
RUN wget -q https://golang.org/dl/$GO \
|
||||
&& rm -rf /usr/local/go \
|
||||
&& tar -C /usr/local -xzf $GO \
|
||||
&& rm $GO
|
||||
ENV PATH="${PATH}:/usr/local/go/bin"
|
||||
RUN go version
|
||||
|
||||
# go deps layer
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
# app build layer
|
||||
COPY ./ ./
|
||||
COPY pkg ./pkg
|
||||
COPY cmd ./cmd
|
||||
COPY Makefile .
|
||||
RUN make build
|
||||
|
||||
# base image
|
||||
|
|
@ -42,16 +42,9 @@ FROM debian:bullseye-slim
|
|||
ARG BUILD_PATH
|
||||
WORKDIR /usr/local/share/cloud-game
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
ca-certificates \
|
||||
libvpx6 \
|
||||
libx264-160 \
|
||||
libopus0 \
|
||||
libopusfile0 \
|
||||
libsdl2-2.0-0 \
|
||||
libgl1-mesa-glx \
|
||||
xvfb \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY scripts/install.sh install.sh
|
||||
RUN bash install.sh && \
|
||||
rm -rf /var/lib/apt/lists/* install.sh
|
||||
|
||||
COPY --from=build ${BUILD_PATH}/bin/ ./
|
||||
RUN cp -s $(pwd)/* /usr/local/bin
|
||||
|
|
|
|||
21
Makefile
vendored
21
Makefile
vendored
|
|
@ -60,17 +60,17 @@ clean:
|
|||
@go clean ./cmd/*
|
||||
|
||||
build:
|
||||
go build -a -tags netgo -ldflags '-w' -o bin/coordinator ./cmd/coordinator
|
||||
go build ${WORKER_BUILD_PARAMS} -a -tags netgo -ldflags '-w' -o bin/worker ./cmd/worker
|
||||
CGO_ENABLED=0 go build -ldflags '-w -s' -o bin/coordinator$(EXT) ./cmd/coordinator
|
||||
go build -buildmode=exe -tags static -ldflags '-w -s' -o bin/worker$(EXT) ./cmd/worker
|
||||
|
||||
dev.tools:
|
||||
./hack/scripts/install_tools.sh
|
||||
verify-cores:
|
||||
go test -run TestAllEmulatorRooms ./pkg/worker/room -v -renderFrames $(GL_CTX) -outputPath "../../../_rendered"
|
||||
|
||||
dev.build: compile build
|
||||
|
||||
dev.build-local:
|
||||
go build -o bin/coordinator ./cmd/coordinator
|
||||
go build ${WORKER_BUILD_PARAMS} -o bin/worker ./cmd/worker
|
||||
CGO_ENABLED=0 go build -o bin/coordinator ./cmd/coordinator
|
||||
go build -buildmode=exe -o bin/worker ./cmd/worker
|
||||
|
||||
dev.run: dev.build-local
|
||||
./bin/coordinator --v=5 &
|
||||
|
|
@ -86,13 +86,15 @@ dev.run-docker:
|
|||
# Folder structure:
|
||||
# - assets/
|
||||
# - games/ (shared between both executables)
|
||||
# - emulator/libretro/cores/ (filtered by extension)
|
||||
# - cores/ (filtered by extension)
|
||||
# - web/
|
||||
# - coordinator
|
||||
# - worker
|
||||
# - config.yaml (shared)
|
||||
#
|
||||
# Config params:
|
||||
# - RELEASE_DIR: the name of the output folder (default: release).
|
||||
# - CONFIG_DIR: search dir for core config files.
|
||||
# - DLIB_TOOL: the name of a dynamic lib copy tool (with params) (e.g., ldd -x -y; defalut: ldd).
|
||||
# - DLIB_SEARCH_PATTERN: a grep filter of the output of the DLIB_TOOL (e.g., mylib.so; default: .*so).
|
||||
# Be aware that this search pattern will return only matched regular expression part and not the whole line.
|
||||
|
|
@ -100,15 +102,18 @@ dev.run-docker:
|
|||
# Makefile special symbols should be escaped with \.
|
||||
# - DLIB_ALTER: a special flag to use altered dynamic copy lib tool for macOS only.
|
||||
# - CORE_EXT: a glob pattern to filter the cores that are copied into the release.
|
||||
# - CFG_EXT: a glob pattern to copy config file into the release (default: *.cfg).
|
||||
#
|
||||
# Example:
|
||||
# make release DLIB_TOOL="ldd -x" DLIB_SEARCH_PATTERN=/usr/lib.*\\\\s CORE_EXT=*.so
|
||||
#
|
||||
RELEASE_DIR ?= release
|
||||
CONFIG_DIR = configs
|
||||
DLIB_TOOL ?= ldd
|
||||
DLIB_SEARCH_PATTERN ?= .*so
|
||||
DLIB_ALTER ?= false
|
||||
CORE_EXT ?= *_libretro.so
|
||||
CFG_EXT ?= *.cfg
|
||||
COORDINATOR_DIR = ./$(RELEASE_DIR)
|
||||
WORKER_DIR = ./$(RELEASE_DIR)
|
||||
CORES_DIR = assets/cores
|
||||
|
|
@ -133,6 +138,8 @@ release: clean build
|
|||
cp -R ./$(GAMES_DIR) $(WORKER_DIR)/assets
|
||||
endif
|
||||
mkdir -p $(WORKER_DIR)/$(CORES_DIR)
|
||||
cp ./$(CORES_DIR)/$(CFG_EXT) $(WORKER_DIR)/$(CORES_DIR)
|
||||
ifneq (,$(wildcard ./$(CORES_DIR)/$(CORE_EXT)))
|
||||
cp -R ./$(CORES_DIR)/$(CORE_EXT) $(WORKER_DIR)/$(CORES_DIR)
|
||||
endif
|
||||
cp ./$(CONFIG_DIR)/config.yaml ./$(RELEASE_DIR)
|
||||
|
|
|
|||
6
README.md
vendored
6
README.md
vendored
|
|
@ -45,13 +45,13 @@ Install Golang https://golang.org/doc/install . Because the project uses GoModul
|
|||
* 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 libx264-dev libopus-dev libopusfile-dev libsdl2-dev
|
||||
apt-get install -y make gcc pkg-config libvpx-dev libx264-dev libopus-dev libsdl2-dev
|
||||
|
||||
# MacOS
|
||||
brew install pkg-config libvpx x264 opus opusfile sdl2
|
||||
brew install pkg-config libvpx x264 opus sdl2
|
||||
|
||||
# Windows (MSYS2)
|
||||
pacman -Sy --noconfirm --needed git make mingw-w64-x86_64-{gcc,pkg-config,dlfcn,libvpx,x264-git,opusfile,SDL2}
|
||||
pacman -Sy --noconfirm --needed git make mingw-w64-x86_64-{gcc,pkg-config,dlfcn,libvpx,opus,x264-git,SDL2}
|
||||
```
|
||||
|
||||
Because the coordinator and workers need to run simultaneously. Workers connect to the coordinator.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"math/rand"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
config "github.com/giongto35/cloud-game/v2/pkg/config/coordinator"
|
||||
|
|
@ -35,12 +36,18 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, os.Interrupt)
|
||||
select {
|
||||
case <-stop:
|
||||
glog.Infoln("Received SIGTERM, Quiting Coordinator")
|
||||
o.Shutdown()
|
||||
cancelCtx()
|
||||
}
|
||||
signals := make(chan os.Signal, 1)
|
||||
done := make(chan struct{}, 1)
|
||||
|
||||
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
sig := <-signals
|
||||
glog.V(4).Infof("[coordinator] Shutting down [os:%v]", sig)
|
||||
done <- struct{}{}
|
||||
}()
|
||||
|
||||
<-done
|
||||
o.Shutdown()
|
||||
cancelCtx()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"math/rand"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
config "github.com/giongto35/cloud-game/v2/pkg/config/worker"
|
||||
|
|
@ -35,14 +36,20 @@ func run() {
|
|||
wrk := worker.New(ctx, conf)
|
||||
wrk.Run()
|
||||
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, os.Interrupt)
|
||||
select {
|
||||
case <-stop:
|
||||
glog.V(4).Info("[worker] Shutting down")
|
||||
wrk.Shutdown()
|
||||
cancelCtx()
|
||||
}
|
||||
signals := make(chan os.Signal, 1)
|
||||
done := make(chan struct{}, 1)
|
||||
|
||||
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
sig := <-signals
|
||||
glog.V(4).Infof("[worker] Shutting down [os:%v]", sig)
|
||||
done <- struct{}{}
|
||||
}()
|
||||
|
||||
<-done
|
||||
wrk.Shutdown()
|
||||
cancelCtx()
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
|||
23
go.mod
vendored
23
go.mod
vendored
|
|
@ -3,7 +3,7 @@ module github.com/giongto35/cloud-game/v2
|
|||
go 1.13
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.80.0 // indirect
|
||||
cloud.google.com/go v0.81.0 // indirect
|
||||
cloud.google.com/go/storage v1.14.0
|
||||
github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec
|
||||
github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3
|
||||
|
|
@ -12,30 +12,27 @@ require (
|
|||
github.com/gofrs/flock v0.8.0
|
||||
github.com/gofrs/uuid v4.0.0+incompatible
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
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/pelletier/go-toml v1.9.0 // indirect
|
||||
github.com/pion/dtls/v2 v2.0.9 // indirect
|
||||
github.com/pion/interceptor v0.0.12
|
||||
github.com/pion/rtp v1.6.2
|
||||
github.com/pion/sctp v1.7.12 // indirect
|
||||
github.com/pion/udp v0.1.1 // indirect
|
||||
github.com/pion/webrtc/v3 v3.0.19
|
||||
github.com/pion/webrtc/v3 v3.0.20
|
||||
github.com/prometheus/client_golang v1.10.0
|
||||
github.com/prometheus/common v0.20.0 // indirect
|
||||
github.com/sergystepanov/x264-go/v2 v2.0.0-20210221160055-cd2aaf7070fc
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/veandco/go-sdl2 v0.4.5
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/net v0.0.0-20210330142815-c8897c278d10 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect
|
||||
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181 // indirect
|
||||
google.golang.org/api v0.43.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee // indirect
|
||||
gopkg.in/hraban/opus.v2 v2.0.0-20201025103112-d779bb1cc5a2
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 // indirect
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210405174219-a39eb2f71cb9 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
|
|
|||
55
go.sum
vendored
55
go.sum
vendored
|
|
@ -18,8 +18,8 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW
|
|||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.80.0 h1:kAdyAMrj9CjqOSGiluseVjIgAyQ3uxADYtUYR6MwYeY=
|
||||
cloud.google.com/go v0.80.0/go.mod h1:fqpb6QRi1CFGAMXDoE72G+b+Ybv7dMB/T1tbExDHktI=
|
||||
cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
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=
|
||||
|
|
@ -42,7 +42,6 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
|
|||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
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=
|
||||
|
|
@ -113,7 +112,6 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2
|
|||
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/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-20210315015930-ae072cafe09d h1:o81yRlBATU4PRn97lydmsq8hTRNXI4wlR/VvUQhFRVY=
|
||||
github.com/go-gl/gl v0.0.0-20210315015930-ae072cafe09d/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
|
||||
|
|
@ -141,8 +139,9 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
|
|||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
|
|
@ -261,7 +260,6 @@ 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=
|
||||
|
|
@ -276,7 +274,6 @@ 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=
|
||||
|
|
@ -332,15 +329,16 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw
|
|||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
|
||||
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.0 h1:NOd0BRdOKpPf0SxkL3HxSQOG7rNh+4kl6PHcBPFs7Q0=
|
||||
github.com/pelletier/go-toml v1.9.0/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pion/datachannel v1.4.21 h1:3ZvhNyfmxsAqltQrApLPQMhSFNA+aT87RqyCq4OXmf0=
|
||||
github.com/pion/datachannel v1.4.21/go.mod h1:oiNyP4gHx2DIwRzX/MFyH0Rz/Gz05OgBlayAI2hAWjg=
|
||||
github.com/pion/dtls/v2 v2.0.8 h1:reGe8rNIMfO/UAeFLqO61tl64t154Qfkr4U3Gzu1tsg=
|
||||
github.com/pion/dtls/v2 v2.0.8/go.mod h1:QuDII+8FVvk9Dp5t5vYIMTo7hh7uBkra+8QIm7QGm10=
|
||||
github.com/pion/dtls/v2 v2.0.9 h1:7Ow+V++YSZQMYzggI0P9vLJz/hUFcffsfGMfT/Qy+u8=
|
||||
github.com/pion/dtls/v2 v2.0.9/go.mod h1:O0Wr7si/Zj5/EBFlDzDd6UtVxx25CE1r7XM7BQKYQho=
|
||||
github.com/pion/ice/v2 v2.0.16 h1:K6bzD8ef9vMKbGMTHaUweHXEyuNGnvr2zdqKoLKZPn0=
|
||||
github.com/pion/ice/v2 v2.0.16/go.mod h1:SJNJzC27gDZoOW0UoxIoC8Hf2PDxG28hQyNdSexDu38=
|
||||
github.com/pion/interceptor v0.0.12 h1:eC1iVneBIAQJEfaNAfDqAncJWhMDAnaXPRCJsltdokE=
|
||||
|
|
@ -356,7 +354,6 @@ github.com/pion/rtcp v1.2.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE
|
|||
github.com/pion/rtp v1.6.2 h1:iGBerLX6JiDjB9NXuaPzHyxHFG9JsIEdgwTC0lp5n/U=
|
||||
github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/sctp v1.7.10/go.mod h1:EhpTUQu1/lcK3xI+eriS6/96fWetHGCvBi9MSsnaBN0=
|
||||
github.com/pion/sctp v1.7.11/go.mod h1:EhpTUQu1/lcK3xI+eriS6/96fWetHGCvBi9MSsnaBN0=
|
||||
github.com/pion/sctp v1.7.12 h1:GsatLufywVruXbZZT1CKg+Jr8ZTkwiPnmUC/oO9+uuY=
|
||||
github.com/pion/sctp v1.7.12/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s=
|
||||
github.com/pion/sdp/v3 v3.0.4 h1:2Kf+dgrzJflNCSw3TV5v2VLeI0s/qkzy2r5jlR0wzf8=
|
||||
|
|
@ -375,8 +372,8 @@ github.com/pion/turn/v2 v2.0.5/go.mod h1:APg43CFyt/14Uy7heYUOGWdkem/Wu4PhCO/bjyr
|
|||
github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths=
|
||||
github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o=
|
||||
github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M=
|
||||
github.com/pion/webrtc/v3 v3.0.19 h1:h3EOMuMNYkJ0X2w1iKNGGBLFN7M/Max0vNUF9IUXqBc=
|
||||
github.com/pion/webrtc/v3 v3.0.19/go.mod h1:P/aoizAjeMUh61uAH58BRypn97IKjcLtIAm/mHqovJw=
|
||||
github.com/pion/webrtc/v3 v3.0.20 h1:Jj0sk45MqQdkR24E1wbFRmOzb1Lv258ot9zd2fYB/Pw=
|
||||
github.com/pion/webrtc/v3 v3.0.20/go.mod h1:0eJnCpQrUMpRnvyonw4ZiWClToerpixrZ2KcoTxvX9M=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
|
|
@ -421,8 +418,6 @@ 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-20210221160055-cd2aaf7070fc h1:WCNpo7QJb7uAA8qMgTBe459EDJCwarm/wbPERNPSt00=
|
||||
github.com/sergystepanov/x264-go/v2 v2.0.0-20210221160055-cd2aaf7070fc/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=
|
||||
|
|
@ -570,8 +565,9 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210330142815-c8897c278d10 h1:j6SlnKgJhONcqBZAH/cLNz6hg79L7Q18RY4BiN0r0LI=
|
||||
golang.org/x/net v0.0.0-20210330142815-c8897c278d10/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
|
@ -583,8 +579,8 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ
|
|||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 h1:D7nTwh4J0i+5mW4Zjzn5omvlr6YBcWywE6KOcatyNxY=
|
||||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/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=
|
||||
|
|
@ -641,7 +637,6 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/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/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-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -651,12 +646,11 @@ golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210314195730-07df6a141424/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181 h1:64ChN/hjER/taL4YJuA+gpLfIMT+/NFherRZixbxOhg=
|
||||
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/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=
|
||||
|
|
@ -665,8 +659,9 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
|||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
|
@ -751,7 +746,6 @@ google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ
|
|||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.42.0/go.mod h1:+Oj4s6ch2SEGtPjGqfUfZonBH0GjQH89gTeKKAEGZKI=
|
||||
google.golang.org/api v0.43.0 h1:4sAyIHT6ZohtAQDoxws+ez7bROYmUlOVvsUscYCDTqA=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
|
|
@ -803,11 +797,10 @@ google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6D
|
|||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210312152112-fc591d9ea70f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210323160006-e668133fea6a/go.mod h1:f2Bd7+2PlaVKmvKQ52aspJZXIDaRQBVdOOBfJ5i8OEs=
|
||||
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee h1:vVeMwkgjjF0rgUTvAJkHJC5hUf50yFdZFDpBgK2kVXI=
|
||||
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210405174219-a39eb2f71cb9 h1:Uga0hMhZnzB159cnlmhVPgEmZTwoZqwOb7e0pu+rlNI=
|
||||
google.golang.org/genproto v0.0.0-20210405174219-a39eb2f71cb9/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||
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=
|
||||
|
|
@ -854,8 +847,6 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS
|
|||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/hraban/opus.v2 v2.0.0-20201025103112-d779bb1cc5a2 h1:sxrRNhZ+cNxxLwPw/vV8gNsz+bbqRQiZHBYBJfpyNoQ=
|
||||
gopkg.in/hraban/opus.v2 v2.0.0-20201025103112-d779bb1cc5a2/go.mod h1:/L5E7a21VWl8DeuCPKxQBdVG5cy+L0MRZ08B1wnqt7g=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
|
|
|
|||
|
|
@ -293,14 +293,14 @@ func (o *Server) getWorkerFromAddress(address string) *WorkerClient {
|
|||
func (o *Server) findBestServerFromBrowser(workerClients map[string]*WorkerClient, client *BrowserClient, zone string) (string, error) {
|
||||
// TODO: Find best Server by latency, currently return by ping
|
||||
if len(workerClients) == 0 {
|
||||
return "", errors.New("No server found")
|
||||
return "", errors.New("no server found")
|
||||
}
|
||||
|
||||
latencies := o.getLatencyMapFromBrowser(workerClients, client)
|
||||
client.Println("Latency map", latencies)
|
||||
|
||||
if len(latencies) == 0 {
|
||||
return "", errors.New("No server found")
|
||||
return "", errors.New("no server found")
|
||||
}
|
||||
|
||||
var bestWorker *WorkerClient
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ type (
|
|||
PacketHandler func(resp WSPacket) (req WSPacket)
|
||||
)
|
||||
|
||||
var EmptyPacket = WSPacket{}
|
||||
var (
|
||||
EmptyPacket = WSPacket{}
|
||||
HeartbeatPacket = WSPacket{ID: "heartbeat"}
|
||||
)
|
||||
|
||||
const WSWait = 20 * time.Second
|
||||
|
||||
|
|
@ -153,20 +156,22 @@ func (c *Client) SyncSend(request WSPacket) (response WSPacket) {
|
|||
// }
|
||||
//}
|
||||
|
||||
// Heartbeat maintains connection to server
|
||||
// Heartbeat maintains connection to coordinator.
|
||||
// Blocking.
|
||||
func (c *Client) Heartbeat() {
|
||||
// send heartbeat every 1s
|
||||
timer := time.Tick(time.Second)
|
||||
|
||||
for range timer {
|
||||
t := time.NewTicker(time.Second)
|
||||
// don't wait 1 second
|
||||
c.Send(HeartbeatPacket, nil)
|
||||
for {
|
||||
select {
|
||||
case <-c.Done:
|
||||
log.Println("Close heartbeat")
|
||||
t.Stop()
|
||||
log.Printf("Close heartbeat")
|
||||
return
|
||||
default:
|
||||
case <-t.C:
|
||||
c.Send(HeartbeatPacket, nil)
|
||||
}
|
||||
// !to resolve cycle deps
|
||||
c.Send(WSPacket{ID: "heartbeat"}, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/cavaliercoder/grab"
|
||||
)
|
||||
|
|
@ -12,8 +14,17 @@ type GrabDownloader struct {
|
|||
}
|
||||
|
||||
func NewGrabDownloader() GrabDownloader {
|
||||
client := grab.Client{
|
||||
UserAgent: "Cloud-Game/2.2",
|
||||
HTTPClient: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
return GrabDownloader{
|
||||
client: grab.NewClient(),
|
||||
client: &client,
|
||||
concurrency: 5,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
872
pkg/encoder/h264/libx264.go
Normal file
872
pkg/encoder/h264/libx264.go
Normal file
|
|
@ -0,0 +1,872 @@
|
|||
// Implements cgo bindings for [x264](https://www.videolan.org/developers/x264.html) library.
|
||||
package h264
|
||||
|
||||
/*
|
||||
#cgo pkg-config: x264
|
||||
#cgo CFLAGS: -Wall -O3
|
||||
|
||||
#include "stdint.h"
|
||||
#include "x264.h"
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
const Build = C.X264_BUILD
|
||||
|
||||
/* T is opaque handler for encoder */
|
||||
type T struct{}
|
||||
|
||||
/****************************************************************************
|
||||
* NAL structure and functions
|
||||
****************************************************************************/
|
||||
|
||||
/* enum nal_unit_type_e */
|
||||
const (
|
||||
NalUnknown = 0
|
||||
NalSlice = 1
|
||||
NalSliceDpa = 2
|
||||
NalSliceDpb = 3
|
||||
NalSliceDpc = 4
|
||||
NalSliceIdr = 5 /* ref_idc != 0 */
|
||||
NalSei = 6 /* ref_idc == 0 */
|
||||
NalSps = 7
|
||||
NalPps = 8
|
||||
NalAud = 9
|
||||
NalFiller = 12
|
||||
/* ref_idc == 0 for 6,9,10,11,12 */
|
||||
)
|
||||
|
||||
/* enum nal_priority_e */
|
||||
const (
|
||||
NalPriorityDisposable = 0
|
||||
NalPriorityLow = 1
|
||||
NalPriorityHigh = 2
|
||||
NalPriorityHighest = 3
|
||||
)
|
||||
|
||||
/* The data within the payload is already NAL-encapsulated; the ref_idc and type
|
||||
* are merely in the struct for easy access by the calling application.
|
||||
* All data returned in an x264_nal_t, including the data in p_payload, is no longer
|
||||
* valid after the next call to x264_encoder_encode. Thus it must be used or copied
|
||||
* before calling x264_encoder_encode or x264_encoder_headers again. */
|
||||
type Nal struct {
|
||||
IRefIdc int32 /* nal_priority_e */
|
||||
IType int32 /* nal_unit_type_e */
|
||||
BLongStartcode int32
|
||||
IFirstMb int32 /* If this NAL is a slice, the index of the first MB in the slice. */
|
||||
ILastMb int32 /* If this NAL is a slice, the index of the last MB in the slice. */
|
||||
|
||||
/* Size of payload (including any padding) in bytes. */
|
||||
IPayload int32
|
||||
/* If param->b_annexb is set, Annex-B bytestream with startcode.
|
||||
* Otherwise, startcode is replaced with a 4-byte size.
|
||||
* This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
|
||||
/* C.uint8_t */
|
||||
PPayload unsafe.Pointer
|
||||
|
||||
/* Size of padding in bytes. */
|
||||
IPadding int32
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Encoder parameters
|
||||
****************************************************************************/
|
||||
/* CPU flags */
|
||||
|
||||
const (
|
||||
/* x86 */
|
||||
CpuMmx uint32 = 1 << 0
|
||||
CpuMmx2 uint32 = 1 << 1 /* MMX2 aka MMXEXT aka ISSE */
|
||||
CpuMmxext = CpuMmx2
|
||||
CpuSse uint32 = 1 << 2
|
||||
CpuSse2 uint32 = 1 << 3
|
||||
CpuLzcnt uint32 = 1 << 4
|
||||
CpuSse3 uint32 = 1 << 5
|
||||
CpuSsse3 uint32 = 1 << 6
|
||||
CpuSse4 uint32 = 1 << 7 /* SSE4.1 */
|
||||
CpuSse42 uint32 = 1 << 8 /* SSE4.2 */
|
||||
CpuAvx uint32 = 1 << 9 /* Requires OS support even if YMM registers aren't used */
|
||||
CpuXop uint32 = 1 << 10 /* AMD XOP */
|
||||
CpuFma4 uint32 = 1 << 11 /* AMD FMA4 */
|
||||
CpuFma3 uint32 = 1 << 12
|
||||
CpuBmi1 uint32 = 1 << 13
|
||||
CpuBmi2 uint32 = 1 << 14
|
||||
CpuAvx2 uint32 = 1 << 15
|
||||
CpuAvx512 uint32 = 1 << 16 /* AVX-512 {F, CD, BW, DQ, VL}, requires OS support */
|
||||
/* x86 modifiers */
|
||||
CpuCacheline32 uint32 = 1 << 17 /* avoid memory loads that span the border between two cachelines */
|
||||
CpuCacheline64 uint32 = 1 << 18 /* 32/64 is the size of a cacheline in bytes */
|
||||
CpuSse2IsSlow uint32 = 1 << 19 /* avoid most SSE2 functions on Athlon64 */
|
||||
CpuSse2IsFast uint32 = 1 << 20 /* a few functions are only faster on Core2 and Phenom */
|
||||
CpuSlowShuffle uint32 = 1 << 21 /* The Conroe has a slow shuffle unit (relative to overall SSE performance) */
|
||||
CpuStackMod4 uint32 = 1 << 22 /* if stack is only mod4 and not mod16 */
|
||||
CpuSlowAtom uint32 = 1 << 23 /* The Atom is terrible: slow SSE unaligned loads, slow
|
||||
* SIMD multiplies, slow SIMD variable shifts, slow pshufb,
|
||||
* cacheline split penalties -- gather everything here that
|
||||
* isn't shared by other CPUs to avoid making half a dozen
|
||||
* new SLOW flags. */
|
||||
CpuSlowPshufb uint32 = 1 << 24 /* such as on the Intel Atom */
|
||||
CpuSlowPalignr uint32 = 1 << 25 /* such as on the AMD Bobcat */
|
||||
|
||||
/* PowerPC */
|
||||
CpuAltivec uint32 = 0x0000001
|
||||
|
||||
/* ARM and AArch64 */
|
||||
CpuArmv6 uint32 = 0x0000001
|
||||
CpuNeon uint32 = 0x0000002 /* ARM NEON */
|
||||
CpuFastNeonMrc uint32 = 0x0000004 /* Transfer from NEON to ARM register is fast (Cortex-A9) */
|
||||
CpuArmv8 uint32 = 0x0000008
|
||||
|
||||
/* MIPS */
|
||||
CpuMsa uint32 = 0x0000001 /* MIPS MSA */
|
||||
|
||||
/* Analyse flags */
|
||||
AnalyseI4x4 uint32 = 0x0001 /* Analyse i4x4 */
|
||||
AnalyseI8x8 uint32 = 0x0002 /* Analyse i8x8 (requires 8x8 transform) */
|
||||
AnalysePsub16x16 uint32 = 0x0010 /* Analyse p16x8, p8x16 and p8x8 */
|
||||
AnalysePsub8x8 uint32 = 0x0020 /* Analyse p8x4, p4x8, p4x4 */
|
||||
AnalyseBsub16x16 uint32 = 0x0100 /* Analyse b16x8, b8x16 and b8x8 */
|
||||
|
||||
DirectPredNone = 0
|
||||
DirectPredSpatial = 1
|
||||
DirectPredTemporal = 2
|
||||
DirectPredAuto = 3
|
||||
MeDia = 0
|
||||
MeHex = 1
|
||||
MeUmh = 2
|
||||
MeEsa = 3
|
||||
MeTesa = 4
|
||||
CqmFlat = 0
|
||||
CqmJvt = 1
|
||||
CqmCustom = 2
|
||||
RcCqp = 0
|
||||
RcCrf = 1
|
||||
RcAbr = 2
|
||||
QpAuto = 0
|
||||
AqNone = 0
|
||||
AqVariance = 1
|
||||
AqAutovariance = 2
|
||||
AqAutovarianceBiased = 3
|
||||
BAdaptNone = 0
|
||||
BAdaptFast = 1
|
||||
BAdaptTrellis = 2
|
||||
WeightpNone = 0
|
||||
WeightpSimple = 1
|
||||
WeightpSmart = 2
|
||||
BPyramidNone = 0
|
||||
BPyramidStrict = 1
|
||||
BPyramidNormal = 2
|
||||
KeyintMinAuto = 0
|
||||
KeyintMaxInfinite = 1 << 30
|
||||
|
||||
/* AVC-Intra flavors */
|
||||
AvcintraFlavorPanasonic = 0
|
||||
AvcintraFlavorSony = 1
|
||||
|
||||
/* !to add missing names */
|
||||
/* static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 }; */
|
||||
/* static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 }; */
|
||||
/* static const char * const x264_b_pyramid_names[] = { "none", "strict", "normal", 0 }; */
|
||||
/* static const char * const x264_overscan_names[] = { "undef", "show", "crop", 0 }; */
|
||||
/* static const char * const x264_vidformat_names[] = { "component", "pal", "ntsc", "secam", "mac", "undef", 0 }; */
|
||||
/* static const char * const x264_fullrange_names[] = { "off", "on", 0 }; */
|
||||
/* static const char * const x264_colorprim_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", "bt2020", "smpte428", "smpte431", "smpte432", 0 }; */
|
||||
/* static const char * const x264_transfer_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", "log316", "iec61966-2-4", "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", "smpte2084", "smpte428", "arib-std-b67", 0 }; */
|
||||
/* static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", "bt2020nc", "bt2020c", "smpte2085", "chroma-derived-nc", "chroma-derived-c", "ICtCp", 0 }; */
|
||||
/* static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 }; */
|
||||
/* static const char * const x264_avcintra_flavor_names[] = { "panasonic", "sony", 0 }; */
|
||||
|
||||
/* Colorspace type */
|
||||
CspMask = 0x00ff /* */
|
||||
CspNone = 0x0000 /* Invalid mode */
|
||||
CspI400 = 0x0001 /* monochrome 4:0:0 */
|
||||
CspI420 = 0x0002 /* yuv 4:2:0 planar */
|
||||
CspYv12 = 0x0003 /* yvu 4:2:0 planar */
|
||||
CspNv12 = 0x0004 /* yuv 4:2:0, with one y plane and one packed u+v */
|
||||
CspNv21 = 0x0005 /* yuv 4:2:0, with one y plane and one packed v+u */
|
||||
CspI422 = 0x0006 /* yuv 4:2:2 planar */
|
||||
CspYv16 = 0x0007 /* yvu 4:2:2 planar */
|
||||
CspNv16 = 0x0008 /* yuv 4:2:2, with one y plane and one packed u+v */
|
||||
CspYuyv = 0x0009 /* yuyv 4:2:2 packed */
|
||||
CspUyvy = 0x000a /* uyvy 4:2:2 packed */
|
||||
CspV210 = 0x000b /* 10-bit yuv 4:2:2 packed in 32 */
|
||||
CspI444 = 0x000c /* yuv 4:4:4 planar */
|
||||
CspYv24 = 0x000d /* yvu 4:4:4 planar */
|
||||
CspBgr = 0x000e /* packed bgr 24bits */
|
||||
CspBgra = 0x000f /* packed bgr 32bits */
|
||||
CspRgb = 0x0010 /* packed rgb 24bits */
|
||||
CspMax = 0x0011 /* end of list */
|
||||
CspVflip = 0x1000 /* the csp is vertically flipped */
|
||||
CspHighDepth = 0x2000 /* the csp has a depth of 16 bits per pixel component */
|
||||
|
||||
/* Slice type */
|
||||
TypeAuto = 0x0000 /* Let x264 choose the right type */
|
||||
TypeIdr = 0x0001
|
||||
TypeI = 0x0002
|
||||
TypeP = 0x0003
|
||||
TypeBref = 0x0004 /* Non-disposable B-frame */
|
||||
TypeB = 0x0005
|
||||
TypeKeyframe = 0x0006 /* IDR or I depending on b_open_gop option */
|
||||
/* !to reimplement macro */
|
||||
/* #define IS_X264_TYPE_I(x) ((x)==X264_TYPE_I || (x)==X264_TYPE_IDR || (x)==X264_TYPE_KEYFRAME) */
|
||||
/* #define IS_X264_TYPE_B(x) ((x)==X264_TYPE_B || (x)==X264_TYPE_BREF) */
|
||||
|
||||
/* Log level */
|
||||
LogNone = -1
|
||||
LogError = 0
|
||||
LogWarning = 1
|
||||
LogInfo = 2
|
||||
LogDebug = 3
|
||||
|
||||
/* Threading */
|
||||
ThreadsAuto = 0 /* Automatically select optimal number of threads */
|
||||
SyncLookaheadAuto = -1 /* Automatically select optimal lookahead thread buffer size */
|
||||
|
||||
/* HRD */
|
||||
NalHrdNone = 0
|
||||
NalHrdVbr = 1
|
||||
NalHrdCbr = 2
|
||||
)
|
||||
|
||||
const (
|
||||
/* The macroblock is constant and remains unchanged from the previous frame. */
|
||||
MbinfoConstant = 1 << 0
|
||||
/* More flags may be added in the future. */
|
||||
)
|
||||
|
||||
/* Zones: override ratecontrol or other options for specific sections of the video.
|
||||
* See x264_encoder_reconfig() for which options can be changed.
|
||||
* If zones overlap, whichever comes later in the list takes precedence. */
|
||||
type Zone struct {
|
||||
IStart, IEnd int32 /* range of frame numbers */
|
||||
BForceQp int32 /* whether to use qp vs bitrate factor */
|
||||
IQp int32
|
||||
FBitrateFactor float32
|
||||
Param *Param
|
||||
}
|
||||
|
||||
type Param struct {
|
||||
/* CPU flags */
|
||||
Cpu uint32
|
||||
IThreads int32 /* encode multiple frames in parallel */
|
||||
ILookaheadThreads int32 /* multiple threads for lookahead analysis */
|
||||
BSlicedThreads int32 /* Whether to use slice-based threading. */
|
||||
BDeterministic int32 /* whether to allow non-deterministic optimizations when threaded */
|
||||
BCpuIndependent int32 /* force canonical behavior rather than cpu-dependent optimal algorithms */
|
||||
ISyncLookahead int32 /* threaded lookahead buffer */
|
||||
|
||||
/* Video Properties */
|
||||
IWidth int32
|
||||
IHeight int32
|
||||
ICsp int32 /* CSP of encoded bitstream */
|
||||
IBitdepth int32
|
||||
ILevelIdc int32
|
||||
IFrameTotal int32 /* number of frames to encode if known, else 0 */
|
||||
|
||||
/* NAL HRD
|
||||
* Uses Buffering and Picture Timing SEIs to signal HRD
|
||||
* The HRD in H.264 was not designed with VFR in mind.
|
||||
* It is therefore not recommended to use NAL HRD with VFR.
|
||||
* Furthermore, reconfiguring the VBV (via x264_encoder_reconfig)
|
||||
* will currently generate invalid HRD. */
|
||||
INalHrd int32
|
||||
|
||||
Vui struct {
|
||||
/* they will be reduced to be 0 < x <= 65535 and prime */
|
||||
ISarHeight int32
|
||||
ISarWidth int32
|
||||
|
||||
IOverscan int32 /* 0=undef, 1=no overscan, 2=overscan */
|
||||
|
||||
/* see h264 annex E for the values of the following */
|
||||
IVidformat int32
|
||||
BFullrange int32
|
||||
IColorprim int32
|
||||
ITransfer int32
|
||||
IColmatrix int32
|
||||
IChromaLoc int32 /* both top & bottom */
|
||||
}
|
||||
|
||||
/* Bitstream parameters */
|
||||
IFrameReference int32 /* Maximum number of reference frames */
|
||||
IDpbSize int32 /* Force a DPB size larger than that implied by B-frames and reference frames.
|
||||
* Useful in combination with interactive error resilience. */
|
||||
IKeyintMax int32 /* Force an IDR keyframe at this interval */
|
||||
IKeyintMin int32 /* Scenecuts closer together than this are coded as I, not IDR. */
|
||||
IScenecutThreshold int32 /* how aggressively to insert extra I frames */
|
||||
BIntraRefresh int32 /* Whether or not to use periodic intra refresh instead of IDR frames. */
|
||||
|
||||
IBframe int32 /* how many b-frame between 2 references pictures */
|
||||
IBframeAdaptive int32
|
||||
IBframeBias int32
|
||||
IBframePyramid int32 /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */
|
||||
BOpenGop int32
|
||||
BBlurayCompat int32
|
||||
IAvcintraClass int32
|
||||
IAvcintraFlavor int32
|
||||
|
||||
BDeblockingFilter int32
|
||||
IDeblockingFilterAlphac0 int32 /* [-6, 6] -6 light filter, 6 strong */
|
||||
IDeblockingFilterBeta int32 /* [-6, 6] idem */
|
||||
|
||||
BCabac int32
|
||||
ICabacInitIdc int32
|
||||
|
||||
BInterlaced int32
|
||||
BConstrainedIntra int32
|
||||
|
||||
ICqmPreset int32
|
||||
PszCqmFile *int8 /* filename (in UTF-8) of CQM file, JM format */
|
||||
Cqm4iy [16]byte /* used only if i_cqm_preset == X264_CQM_CUSTOM */
|
||||
Cqm4py [16]byte
|
||||
Cqm4ic [16]byte
|
||||
Cqm4pc [16]byte
|
||||
Cqm8iy [64]byte
|
||||
Cqm8py [64]byte
|
||||
Cqm8ic [64]byte
|
||||
Cqm8pc [64]byte
|
||||
|
||||
/* Log */
|
||||
PfLog *[0]byte
|
||||
PLogPrivate unsafe.Pointer
|
||||
ILogLevel int32
|
||||
BFullRecon int32 /* fully reconstruct frames, even when not necessary for encoding. Implied by psz_dump_yuv */
|
||||
PszDumpYuv *int8 /* filename (in UTF-8) for reconstructed frames */
|
||||
|
||||
/* Encoder analyser parameters */
|
||||
Analyse struct {
|
||||
Intra uint32 /* intra partitions */
|
||||
Inter uint32 /* inter partitions */
|
||||
|
||||
BTransform8x8 int32
|
||||
IWeightedPred int32 /* weighting for P-frames */
|
||||
BWeightedBipred int32 /* implicit weighting for B-frames */
|
||||
IDirectMvPred int32 /* spatial vs temporal mv prediction */
|
||||
IChromaQpOffset int32
|
||||
|
||||
IMeMethod int32 /* motion estimation algorithm to use (X264_ME_*) */
|
||||
IMeRange int32 /* integer pixel motion estimation search range (from predicted mv) */
|
||||
IMvRange int32 /* maximum length of a mv (in pixels). -1 = auto, based on level */
|
||||
IMvRangeThread int32 /* minimum space between threads. -1 = auto, based on number of threads. */
|
||||
ISubpelRefine int32 /* subpixel motion estimation quality */
|
||||
BChromaMe int32 /* chroma ME for subpel and mode decision in P-frames */
|
||||
BMixedReferences int32 /* allow each mb partition to have its own reference number */
|
||||
ITrellis int32 /* trellis RD quantization */
|
||||
BFastPskip int32 /* early SKIP detection on P-frames */
|
||||
BDctDecimate int32 /* transform coefficient thresholding on P-frames */
|
||||
INoiseReduction int32 /* adaptive pseudo-deadzone */
|
||||
FPsyRd float32 /* Psy RD strength */
|
||||
FPsyTrellis float32 /* Psy trellis strength */
|
||||
BPsy int32 /* Toggle all psy optimizations */
|
||||
|
||||
BMbInfo int32 /* Use input mb_info data in x264_picture_t */
|
||||
BMbInfoUpdate int32 /* Update the values in mb_info according to the results of encoding. */
|
||||
|
||||
/* the deadzone size that will be used in luma quantization */
|
||||
ILumaDeadzone [2]int32
|
||||
|
||||
BPsnr int32 /* compute and print PSNR stats */
|
||||
BSsim int32 /* compute and print SSIM stats */
|
||||
}
|
||||
|
||||
/* Rate control parameters */
|
||||
Rc struct {
|
||||
IRcMethod int32 /* X264_RC_* */
|
||||
|
||||
IQpConstant int32 /* 0=lossless */
|
||||
IQpMin int32 /* min allowed QP value */
|
||||
IQpMax int32 /* max allowed QP value */
|
||||
IQpStep int32 /* max QP step between frames */
|
||||
|
||||
IBitrate int32
|
||||
FRfConstant float32 /* 1pass VBR, nominal QP */
|
||||
FRfConstantMax float32 /* In CRF mode, maximum CRF as caused by VBV */
|
||||
FRateTolerance float32
|
||||
IVbvMaxBitrate int32
|
||||
IVbvBufferSize int32
|
||||
FVbvBufferInit float32 /* <=1: fraction of buffer_size. >1: kbit */
|
||||
FIpFactor float32
|
||||
FPbFactor float32
|
||||
|
||||
/* VBV filler: force CBR VBV and use filler bytes to ensure hard-CBR.
|
||||
* Implied by NAL-HRD CBR. */
|
||||
BFiller int32
|
||||
|
||||
IAqMode int32 /* psy adaptive QP. (X264_AQ_*) */
|
||||
FAqStrength float32
|
||||
BMbTree int32 /* Macroblock-tree ratecontrol. */
|
||||
ILookahead int32
|
||||
|
||||
/* 2pass */
|
||||
BStatWrite int32 /* Enable stat writing in psz_stat_out */
|
||||
PszStatOut *int8 /* output filename (in UTF-8) of the 2pass stats file */
|
||||
BStatRead int32 /* Read stat from psz_stat_in and use it */
|
||||
PszStatIn *int8 /* input filename (in UTF-8) of the 2pass stats file */
|
||||
|
||||
/* 2pass params (same as ffmpeg ones) */
|
||||
FQcompress float32 /* 0.0 => cbr, 1.0 => constant qp */
|
||||
FQblur float32 /* temporally blur quants */
|
||||
FComplexityBlur float32 /* temporally blur complexity */
|
||||
Zones *Zone /* ratecontrol overrides */
|
||||
IZones int32 /* number of zone_t's */
|
||||
PszZones *int8 /* alternate method of specifying zones */
|
||||
}
|
||||
|
||||
/* Cropping Rectangle parameters: added to those implicitly defined by
|
||||
non-mod16 video resolutions. */
|
||||
CropRect struct {
|
||||
ILeft int32
|
||||
ITop int32
|
||||
IRight int32
|
||||
IBottom int32
|
||||
}
|
||||
|
||||
/* frame packing arrangement flag */
|
||||
IFramePacking int32
|
||||
|
||||
/* alternative transfer SEI */
|
||||
IAlternativeTransfer int32
|
||||
|
||||
/* Muxing parameters */
|
||||
BAud int32 /* generate access unit delimiters */
|
||||
BRepeatHeaders int32 /* put SPS/PPS before each keyframe */
|
||||
BAnnexb int32 /* if set, place start codes (4 bytes) before NAL units,
|
||||
* otherwise place size (4 bytes) before NAL units. */
|
||||
ISpsId int32 /* SPS and PPS id number */
|
||||
BVfrInput int32 /* VFR input. If 1, use timebase and timestamps for ratecontrol purposes.
|
||||
* If 0, use fps only. */
|
||||
BPulldown int32 /* use explicity set timebase for CFR */
|
||||
IFpsNum uint32
|
||||
IFpsDen uint32
|
||||
ITimebaseNum uint32 /* Timebase numerator */
|
||||
ITimebaseDen uint32 /* Timebase denominator */
|
||||
|
||||
BTff int32
|
||||
|
||||
/* Pulldown:
|
||||
* The correct pic_struct must be passed with each input frame.
|
||||
* The input timebase should be the timebase corresponding to the output framerate. This should be constant.
|
||||
* e.g. for 3:2 pulldown timebase should be 1001/30000
|
||||
* The PTS passed with each frame must be the PTS of the frame after pulldown is applied.
|
||||
* Frame doubling and tripling require b_vfr_input set to zero (see H.264 Table D-1)
|
||||
*
|
||||
* Pulldown changes are not clearly defined in H.264. Therefore, it is the calling app's responsibility to manage this.
|
||||
*/
|
||||
|
||||
BPicStruct int32
|
||||
|
||||
/* Fake Interlaced.
|
||||
*
|
||||
* Used only when b_interlaced=0. Setting this flag makes it possible to flag the stream as PAFF interlaced yet
|
||||
* encode all frames progressively. It is useful for encoding 25p and 30p Blu-Ray streams.
|
||||
*/
|
||||
BFakeInterlaced int32
|
||||
|
||||
/* Don't optimize header parameters based on video content, e.g. ensure that splitting an input video, compressing
|
||||
* each part, and stitching them back together will result in identical SPS/PPS. This is necessary for stitching
|
||||
* with container formats that don't allow multiple SPS/PPS. */
|
||||
BStitchable int32
|
||||
|
||||
BOpencl int32 /* use OpenCL when available */
|
||||
IOpenclDevice int32 /* specify count of GPU devices to skip, for CLI users */
|
||||
OpenclDeviceId unsafe.Pointer /* pass explicit cl_device_id as void*, for API users */
|
||||
PszClbinFile *int8 /* filename (in UTF-8) of the compiled OpenCL kernel cache file */
|
||||
|
||||
/* Slicing parameters */
|
||||
iSliceMaxSize int32 /* Max size per slice in bytes; includes estimated NAL overhead. */
|
||||
iSliceMaxMbs int32 /* Max number of MBs per slice; overrides iSliceCount. */
|
||||
iSliceMinMbs int32 /* Min number of MBs per slice */
|
||||
iSliceCount int32 /* Number of slices per frame: forces rectangular slices. */
|
||||
iSliceCountMax int32 /* Absolute cap on slices per frame; stops applying slice-max-size
|
||||
* and slice-max-mbs if this is reached. */
|
||||
|
||||
ParamFree *func(arg unsafe.Pointer)
|
||||
NaluProcess *func(H []T, Nal []Nal, Opaque unsafe.Pointer)
|
||||
|
||||
Opaque unsafe.Pointer
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* H.264 level restriction information
|
||||
****************************************************************************/
|
||||
|
||||
type Level struct {
|
||||
LevelIdc byte
|
||||
Mbps int32 /* max macroblock processing rate (macroblocks/sec) */
|
||||
FrameSize int32 /* max frame size (macroblocks) */
|
||||
Dpb int32 /* max decoded picture buffer (mbs) */
|
||||
Bitrate int32 /* max bitrate (kbit/sec) */
|
||||
Cpb int32 /* max vbv buffer (kbit) */
|
||||
MvRange uint16 /* max vertical mv component range (pixels) */
|
||||
MvsPer2mb byte /* max mvs per 2 consecutive mbs. */
|
||||
SliceRate byte /* ?? */
|
||||
Mincr byte /* min compression ratio */
|
||||
Bipred8x8 byte /* limit bipred to >=8x8 */
|
||||
Direct8x8 byte /* limit b_direct to >=8x8 */
|
||||
FrameOnly byte /* forbid interlacing */
|
||||
}
|
||||
|
||||
type PicStruct int32
|
||||
|
||||
const (
|
||||
PicStructAuto = iota // automatically decide (default)
|
||||
PicStructProgressive = 1 // progressive frame
|
||||
// "TOP" and "BOTTOM" are not supported in x264 (PAFF only)
|
||||
PicStructTopBottom = 4 // top field followed by bottom
|
||||
PicStructBottomTop = 5 // bottom field followed by top
|
||||
PicStructTopBottomTop = 6 // top field, bottom field, top field repeated
|
||||
PicStructBottomTopBottom = 7 // bottom field, top field, bottom field repeated
|
||||
PicStructDouble = 8 // double frame
|
||||
PicStructTriple = 9 // triple frame
|
||||
)
|
||||
|
||||
type Hrd struct {
|
||||
CpbInitialArrivalTime float64
|
||||
CpbFinalArrivalTime float64
|
||||
CpbRemovalTime float64
|
||||
|
||||
DpbOutputTime float64
|
||||
}
|
||||
|
||||
/* Arbitrary user SEI:
|
||||
* Payload size is in bytes and the payload pointer must be valid.
|
||||
* Payload types and syntax can be found in Annex D of the H.264 Specification.
|
||||
* SEI payload alignment bits as described in Annex D must be included at the
|
||||
* end of the payload if needed.
|
||||
* The payload should not be NAL-encapsulated.
|
||||
* Payloads are written first in order of input, apart from in the case when HRD
|
||||
* is enabled where payloads are written after the Buffering Period SEI. */
|
||||
type SeiPayload struct {
|
||||
PayloadSize int32
|
||||
PayloadType int32
|
||||
Payload *byte
|
||||
}
|
||||
|
||||
type Sei struct {
|
||||
NumPayloads int32
|
||||
Payloads *SeiPayload
|
||||
/* In: optional callback to free each payload AND x264_sei_payload_t when used. */
|
||||
SeiFree *func(arg0 unsafe.Pointer)
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
ICsp int32 /* Colorspace */
|
||||
IPlane int32 /* Number of image planes */
|
||||
IStride [4]int32 /* Strides for each plane */
|
||||
Plane [4]unsafe.Pointer /* Pointers to each plane */
|
||||
}
|
||||
|
||||
/* All arrays of data here are ordered as follows:
|
||||
* each array contains one offset per macroblock, in raster scan order. In interlaced
|
||||
* mode, top-field MBs and bottom-field MBs are interleaved at the row level.
|
||||
* Macroblocks are 16x16 blocks of pixels (with respect to the luma plane). For the
|
||||
* purposes of calculating the number of macroblocks, width and height are rounded up to
|
||||
* the nearest 16. If in interlaced mode, height is rounded up to the nearest 32 instead. */
|
||||
type ImageProperties struct {
|
||||
/* In: an array of quantizer offsets to be applied to this image during encoding.
|
||||
* These are added on top of the decisions made by x264.
|
||||
* Offsets can be fractional; they are added before QPs are rounded to integer.
|
||||
* Adaptive quantization must be enabled to use this feature. Behavior if quant
|
||||
* offsets differ between encoding passes is undefined. */
|
||||
QuantOffsets *float32
|
||||
/* In: optional callback to free quant_offsets when used.
|
||||
* Useful if one wants to use a different quant_offset array for each frame. */
|
||||
QuantOffsetsFree *func(arg0 unsafe.Pointer)
|
||||
|
||||
/* In: optional array of flags for each macroblock.
|
||||
* Allows specifying additional information for the encoder such as which macroblocks
|
||||
* remain unchanged. Usable flags are listed below.
|
||||
* x264_param_t.analyse.b_mb_info must be set to use this, since x264 needs to track
|
||||
* extra data internally to make full use of this information.
|
||||
*
|
||||
* Out: if b_mb_info_update is set, x264 will update this array as a result of encoding.
|
||||
*
|
||||
* For "MBINFO_CONSTANT", it will remove this flag on any macroblock whose decoded
|
||||
* pixels have changed. This can be useful for e.g. noting which areas of the
|
||||
* frame need to actually be blitted. Note: this intentionally ignores the effects
|
||||
* of deblocking for the current frame, which should be fine unless one needs exact
|
||||
* pixel-perfect accuracy.
|
||||
*
|
||||
* Results for MBINFO_CONSTANT are currently only set for P-frames, and are not
|
||||
* guaranteed to enumerate all blocks which haven't changed. (There may be false
|
||||
* negatives, but no false positives.)
|
||||
*/
|
||||
MbInfo *byte
|
||||
/* In: optional callback to free mb_info when used. */
|
||||
MbInfoFree *func(arg0 unsafe.Pointer)
|
||||
|
||||
/* Out: SSIM of the the frame luma (if x264_param_t.b_ssim is set) */
|
||||
FSsim float64
|
||||
/* Out: Average PSNR of the frame (if x264_param_t.b_psnr is set) */
|
||||
FPsnrAvg float64
|
||||
/* Out: PSNR of Y, U, and V (if x264_param_t.b_psnr is set) */
|
||||
FPsnr [3]float64
|
||||
|
||||
/* Out: Average effective CRF of the encoded frame */
|
||||
FCrfAvg float64
|
||||
}
|
||||
|
||||
type Picture struct {
|
||||
/* In: force picture type (if not auto)
|
||||
* If x264 encoding parameters are violated in the forcing of picture types,
|
||||
* x264 will correct the input picture type and log a warning.
|
||||
* Out: type of the picture encoded */
|
||||
IType int32
|
||||
/* In: force quantizer for != X264_QP_AUTO */
|
||||
IQpplus1 int32
|
||||
/* In: pic_struct, for pulldown/doubling/etc...used only if b_pic_struct=1.
|
||||
* use pic_struct_e for pic_struct inputs
|
||||
* Out: pic_struct element associated with frame */
|
||||
IPicStruct int32
|
||||
/* Out: whether this frame is a keyframe. Important when using modes that result in
|
||||
* SEI recovery points being used instead of IDR frames. */
|
||||
BKeyframe int32
|
||||
/* In: user pts, Out: pts of encoded picture (user)*/
|
||||
IPts int64
|
||||
/* Out: frame dts. When the pts of the first frame is close to zero,
|
||||
* initial frames may have a negative dts which must be dealt with by any muxer */
|
||||
IDts int64
|
||||
/* In: custom encoding parameters to be set from this frame forwards
|
||||
(in coded order, not display order). If NULL, continue using
|
||||
parameters from the previous frame. Some parameters, such as
|
||||
aspect ratio, can only be changed per-GOP due to the limitations
|
||||
of H.264 itself; in this case, the caller must force an IDR frame
|
||||
if it needs the changed parameter to apply immediately. */
|
||||
Param *Param
|
||||
/* In: raw image data */
|
||||
/* Out: reconstructed image data. x264 may skip part of the reconstruction process,
|
||||
e.g. deblocking, in frames where it isn't necessary. To force complete
|
||||
reconstruction, at a small speed cost, set b_full_recon. */
|
||||
Img Image
|
||||
/* In: optional information to modify encoder decisions for this frame
|
||||
* Out: information about the encoded frame */
|
||||
Prop ImageProperties
|
||||
/* Out: HRD timing information. Output only when i_nal_hrd is set. */
|
||||
Hrdiming Hrd
|
||||
/* In: arbitrary user SEI (e.g subtitles, AFDs) */
|
||||
ExtraSei Sei
|
||||
/* private user data. copied from input to output frames. */
|
||||
Opaque unsafe.Pointer
|
||||
}
|
||||
|
||||
func (p *Picture) freePlane(n int) {
|
||||
C.free(p.Img.Plane[n])
|
||||
}
|
||||
|
||||
func (t *T) cptr() *C.x264_t { return (*C.x264_t)(unsafe.Pointer(t)) }
|
||||
|
||||
func (n *Nal) cptr() *C.x264_nal_t { return (*C.x264_nal_t)(unsafe.Pointer(n)) }
|
||||
|
||||
func (p *Param) cptr() *C.x264_param_t { return (*C.x264_param_t)(unsafe.Pointer(p)) }
|
||||
|
||||
func (p *Picture) cptr() *C.x264_picture_t { return (*C.x264_picture_t)(unsafe.Pointer(p)) }
|
||||
|
||||
// NalEncode - encode Nal.
|
||||
func NalEncode(h *T, dst []byte, nal *Nal) {
|
||||
ch := h.cptr()
|
||||
cdst := (*C.uint8_t)(unsafe.Pointer(&dst[0]))
|
||||
cnal := nal.cptr()
|
||||
C.x264_nal_encode(ch, cdst, cnal)
|
||||
}
|
||||
|
||||
// ParamDefault - fill Param with default values and do CPU detection.
|
||||
func ParamDefault(param *Param) {
|
||||
C.x264_param_default(param.cptr())
|
||||
}
|
||||
|
||||
// ParamParse - set one parameter by name. Returns 0 on success.
|
||||
func ParamParse(param *Param, name string, value string) int32 {
|
||||
cparam := param.cptr()
|
||||
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
|
||||
cvalue := C.CString(value)
|
||||
defer C.free(unsafe.Pointer(cvalue))
|
||||
|
||||
ret := C.x264_param_parse(cparam, cname, cvalue)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// ParamDefaultPreset - the same as ParamDefault, but also use the passed preset and tune to modify the default settings
|
||||
// (either can be nil, which implies no preset or no tune, respectively).
|
||||
//
|
||||
// Currently available presets are, ordered from fastest to slowest:
|
||||
// "ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo".
|
||||
//
|
||||
// Currently available tunings are:
|
||||
// "film", "animation", "grain", "stillimage", "psnr", "ssim", "fastdecode", "zerolatency".
|
||||
//
|
||||
// Returns 0 on success, negative on failure (e.g. invalid preset/tune name).
|
||||
func ParamDefaultPreset(param *Param, preset string, tune string) int32 {
|
||||
cparam := param.cptr()
|
||||
|
||||
cpreset := C.CString(preset)
|
||||
defer C.free(unsafe.Pointer(cpreset))
|
||||
|
||||
ctune := C.CString(tune)
|
||||
defer C.free(unsafe.Pointer(ctune))
|
||||
|
||||
ret := C.x264_param_default_preset(cparam, cpreset, ctune)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// ParamApplyFastfirstpass - if first-pass mode is set (rc.b_stat_read == 0, rc.b_stat_write == 1),
|
||||
// modify the encoder settings to disable options generally not useful on the first pass.
|
||||
func ParamApplyFastfirstpass(param *Param) {
|
||||
cparam := param.cptr()
|
||||
C.x264_param_apply_fastfirstpass(cparam)
|
||||
}
|
||||
|
||||
// ParamApplyProfile - applies the restrictions of the given profile.
|
||||
//
|
||||
// Currently available profiles are, from most to least restrictive:
|
||||
// "baseline", "main", "high", "high10", "high422", "high444".
|
||||
// (can be nil, in which case the function will do nothing).
|
||||
//
|
||||
// Returns 0 on success, negative on failure (e.g. invalid profile name).
|
||||
func ParamApplyProfile(param *Param, profile string) int32 {
|
||||
cparam := param.cptr()
|
||||
|
||||
cprofile := C.CString(profile)
|
||||
defer C.free(unsafe.Pointer(cprofile))
|
||||
|
||||
ret := C.x264_param_apply_profile(cparam, cprofile)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// PictureInit - initialize an Picture. Needs to be done if the calling application
|
||||
// allocates its own Picture as opposed to using PictureAlloc.
|
||||
func PictureInit(pic *Picture) {
|
||||
cpic := pic.cptr()
|
||||
C.x264_picture_init(cpic)
|
||||
}
|
||||
|
||||
// PictureAlloc - alloc data for a Picture. You must call PictureClean on it.
|
||||
// Returns 0 on success, or -1 on malloc failure or invalid colorspace.
|
||||
func PictureAlloc(pic *Picture, iCsp int32, iWidth int32, iHeight int32) int32 {
|
||||
cpic := pic.cptr()
|
||||
|
||||
ciCsp := (C.int)(iCsp)
|
||||
ciWidth := (C.int)(iWidth)
|
||||
ciHeight := (C.int)(iHeight)
|
||||
|
||||
ret := C.x264_picture_alloc(cpic, ciCsp, ciWidth, ciHeight)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// PictureClean - free associated resource for a Picture allocated with PictureAlloc ONLY.
|
||||
func PictureClean(pic *Picture) {
|
||||
cpic := pic.cptr()
|
||||
C.x264_picture_clean(cpic)
|
||||
}
|
||||
|
||||
// EncoderOpen - create a new encoder handler, all parameters from Param are copied.
|
||||
func EncoderOpen(param *Param) *T {
|
||||
cparam := param.cptr()
|
||||
|
||||
ret := C.x264_encoder_open(cparam)
|
||||
v := *(**T)(unsafe.Pointer(&ret))
|
||||
return v
|
||||
}
|
||||
|
||||
// EncoderReconfig - various parameters from Param are copied.
|
||||
// Returns 0 on success, negative on parameter validation error.
|
||||
func EncoderReconfig(enc *T, param *Param) int32 {
|
||||
cenc := enc.cptr()
|
||||
cparam := param.cptr()
|
||||
|
||||
ret := C.x264_encoder_reconfig(cenc, cparam)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// EncoderParameters - copies the current internal set of parameters to the pointer provided.
|
||||
func EncoderParameters(enc *T, param *Param) {
|
||||
cenc := enc.cptr()
|
||||
cparam := param.cptr()
|
||||
|
||||
C.x264_encoder_parameters(cenc, cparam)
|
||||
}
|
||||
|
||||
// EncoderHeaders - return the SPS and PPS that will be used for the whole stream.
|
||||
// Returns the number of bytes in the returned NALs or negative on error.
|
||||
func EncoderHeaders(enc *T, ppNal []*Nal, piNal *int32) int32 {
|
||||
cenc := enc.cptr()
|
||||
|
||||
cppNal := (**C.x264_nal_t)(unsafe.Pointer(&ppNal[0]))
|
||||
cpiNal := (*C.int)(unsafe.Pointer(piNal))
|
||||
|
||||
ret := C.x264_encoder_headers(cenc, cppNal, cpiNal)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// EncoderEncode - encode one picture.
|
||||
// Returns the number of bytes in the returned NALs, negative on error and zero if no NAL units returned.
|
||||
func EncoderEncode(enc *T, ppNal []*Nal, piNal *int32, picIn *Picture, picOut *Picture) int32 {
|
||||
cenc := enc.cptr()
|
||||
|
||||
cppNal := (**C.x264_nal_t)(unsafe.Pointer(&ppNal[0]))
|
||||
cpiNal := (*C.int)(unsafe.Pointer(piNal))
|
||||
|
||||
cpicIn := picIn.cptr()
|
||||
cpicOut := picOut.cptr()
|
||||
|
||||
ret := C.x264_encoder_encode(cenc, cppNal, cpiNal, cpicIn, cpicOut)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// EncoderClose - close an encoder handler.
|
||||
func EncoderClose(enc *T) {
|
||||
cenc := enc.cptr()
|
||||
C.x264_encoder_close(cenc)
|
||||
}
|
||||
|
||||
// EncoderDelayedFrames - return the number of currently delayed (buffered) frames.
|
||||
// This should be used at the end of the stream, to know when you have all the encoded frames.
|
||||
func EncoderDelayedFrames(enc *T) int32 {
|
||||
cenc := enc.cptr()
|
||||
|
||||
ret := C.x264_encoder_delayed_frames(cenc)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// EncoderMaximumDelayedFrames - return the maximum number of delayed (buffered) frames that can occur with the current parameters.
|
||||
func EncoderMaximumDelayedFrames(enc *T) int32 {
|
||||
cenc := enc.cptr()
|
||||
|
||||
ret := C.x264_encoder_maximum_delayed_frames(cenc)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
||||
// EncoderIntraRefresh - If an intra refresh is not in progress, begin one with the next P-frame.
|
||||
// If an intra refresh is in progress, begin one as soon as the current one finishes.
|
||||
// Requires that BIntraRefresh be set.
|
||||
//
|
||||
// Should not be called during an x264_encoder_encode.
|
||||
func EncoderIntraRefresh(enc *T) {
|
||||
cenc := enc.cptr()
|
||||
C.x264_encoder_intra_refresh(cenc)
|
||||
}
|
||||
|
||||
// EncoderInvalidateReference - An interactive error resilience tool, designed for use in a low-latency one-encoder-few-clients system.
|
||||
// Should not be called during an EncoderEncode, but multiple calls can be made simultaneously.
|
||||
//
|
||||
// Returns 0 on success, negative on failure.
|
||||
func EncoderInvalidateReference(enc *T, pts int) int32 {
|
||||
cenc := enc.cptr()
|
||||
cpts := (C.int64_t)(pts)
|
||||
|
||||
ret := C.x264_encoder_invalidate_reference(cenc, cpts)
|
||||
v := (int32)(ret)
|
||||
return v
|
||||
}
|
||||
|
|
@ -1,30 +1,27 @@
|
|||
package h264
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
x264 "github.com/sergystepanov/x264-go/v2/x264c/external"
|
||||
)
|
||||
|
||||
type H264 struct {
|
||||
ref *x264.T
|
||||
ref *T
|
||||
|
||||
width int32
|
||||
lumaSize int32
|
||||
chromaSize int32
|
||||
csp int32
|
||||
nnals int32
|
||||
nals []*x264.Nal
|
||||
nals []*Nal
|
||||
|
||||
// keep monotonic pts to suppress warnings
|
||||
pts int64
|
||||
}
|
||||
|
||||
func NewEncoder(width, height int, options ...Option) (encoder *H264, err error) {
|
||||
libVersion := int(x264.Build)
|
||||
libVersion := int(Build)
|
||||
|
||||
if libVersion < 150 {
|
||||
return nil, fmt.Errorf("x264: the library version should be newer than v150, you have got version %v", libVersion)
|
||||
|
|
@ -46,20 +43,20 @@ func NewEncoder(width, height int, options ...Option) (encoder *H264, err error)
|
|||
}
|
||||
|
||||
if opts.LogLevel > 0 {
|
||||
log.Printf("x264: build v%v", x264.Build)
|
||||
log.Printf("x264: build v%v", Build)
|
||||
}
|
||||
|
||||
param := x264.Param{}
|
||||
param := Param{}
|
||||
if opts.Preset != "" && opts.Tune != "" {
|
||||
if x264.ParamDefaultPreset(¶m, opts.Preset, opts.Tune) < 0 {
|
||||
if ParamDefaultPreset(¶m, opts.Preset, opts.Tune) < 0 {
|
||||
return nil, fmt.Errorf("x264: invalid preset/tune name")
|
||||
}
|
||||
} else {
|
||||
x264.ParamDefault(¶m)
|
||||
ParamDefault(¶m)
|
||||
}
|
||||
|
||||
if opts.Profile != "" {
|
||||
if x264.ParamApplyProfile(¶m, opts.Profile) < 0 {
|
||||
if ParamApplyProfile(¶m, opts.Profile) < 0 {
|
||||
return nil, fmt.Errorf("x264: invalid profile name")
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +65,7 @@ func NewEncoder(width, height int, options ...Option) (encoder *H264, err error)
|
|||
param.IBitdepth = 8
|
||||
|
||||
if libVersion > 155 {
|
||||
param.ICsp = x264.CspI420
|
||||
param.ICsp = CspI420
|
||||
} else {
|
||||
param.ICsp = 1
|
||||
}
|
||||
|
|
@ -76,21 +73,21 @@ func NewEncoder(width, height int, options ...Option) (encoder *H264, err error)
|
|||
param.IHeight = int32(height)
|
||||
param.ILogLevel = opts.LogLevel
|
||||
|
||||
param.Rc.IRcMethod = x264.RcCrf
|
||||
param.Rc.IRcMethod = 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),
|
||||
nals: make([]*Nal, 1),
|
||||
width: int32(width),
|
||||
}
|
||||
|
||||
var picIn x264.Picture
|
||||
x264.PictureInit(&picIn)
|
||||
var picIn Picture
|
||||
PictureInit(&picIn)
|
||||
|
||||
if encoder.ref = x264.EncoderOpen(¶m); encoder.ref == nil {
|
||||
if encoder.ref = EncoderOpen(¶m); encoder.ref == nil {
|
||||
err = fmt.Errorf("x264: cannot open the encoder")
|
||||
return
|
||||
}
|
||||
|
|
@ -98,7 +95,7 @@ func NewEncoder(width, height int, options ...Option) (encoder *H264, err error)
|
|||
}
|
||||
|
||||
func (e *H264) Encode(yuv []byte) []byte {
|
||||
var picIn, picOut x264.Picture
|
||||
var picIn, picOut Picture
|
||||
|
||||
picIn.Img.ICsp = e.csp
|
||||
picIn.Img.IPlane = 3
|
||||
|
|
@ -114,12 +111,12 @@ func (e *H264) Encode(yuv []byte) []byte {
|
|||
e.pts++
|
||||
|
||||
defer func() {
|
||||
C.free(picIn.Img.Plane[0])
|
||||
C.free(picIn.Img.Plane[1])
|
||||
C.free(picIn.Img.Plane[2])
|
||||
picIn.freePlane(0)
|
||||
picIn.freePlane(1)
|
||||
picIn.freePlane(2)
|
||||
}()
|
||||
|
||||
if ret := x264.EncoderEncode(e.ref, e.nals, &e.nnals, &picIn, &picOut); ret > 0 {
|
||||
if ret := EncoderEncode(e.ref, e.nals, &e.nnals, &picIn, &picOut); ret > 0 {
|
||||
return C.GoBytes(e.nals[0].PPayload, C.int(ret))
|
||||
// ret should be equal to writer writes
|
||||
}
|
||||
|
|
@ -127,6 +124,6 @@ func (e *H264) Encode(yuv []byte) []byte {
|
|||
}
|
||||
|
||||
func (e *H264) Shutdown() error {
|
||||
x264.EncoderClose(e.ref)
|
||||
EncoderClose(e.ref)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,10 @@ package opus
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gopkg.in/hraban/opus.v2"
|
||||
)
|
||||
|
||||
type Encoder struct {
|
||||
*opus.Encoder
|
||||
*LibOpusEncoder
|
||||
|
||||
channels int
|
||||
inFrequency int
|
||||
|
|
@ -22,26 +20,26 @@ type Encoder struct {
|
|||
}
|
||||
|
||||
func NewEncoder(inputSampleRate, outputSampleRate, channels int, options ...func(*Encoder) error) (Encoder, error) {
|
||||
encoder, err := opus.NewEncoder(
|
||||
encoder, err := NewOpusEncoder(
|
||||
outputSampleRate,
|
||||
channels,
|
||||
// be aware that low delay option is not optimized for voice
|
||||
opus.AppRestrictedLowdelay,
|
||||
AppRestrictedLowdelay,
|
||||
)
|
||||
if err != nil {
|
||||
return Encoder{}, err
|
||||
}
|
||||
enc := &Encoder{
|
||||
Encoder: encoder,
|
||||
buffer: Buffer{Data: make([]int16, inputSampleRate*20/1000*channels)},
|
||||
channels: channels,
|
||||
inFrequency: inputSampleRate,
|
||||
outFrequency: outputSampleRate,
|
||||
outBufferSize: 1024,
|
||||
onFullBuffer: func(data []byte) {},
|
||||
LibOpusEncoder: encoder,
|
||||
buffer: Buffer{Data: make([]int16, inputSampleRate*20/1000*channels)},
|
||||
channels: channels,
|
||||
inFrequency: inputSampleRate,
|
||||
outFrequency: outputSampleRate,
|
||||
outBufferSize: 1024,
|
||||
onFullBuffer: func(data []byte) {},
|
||||
}
|
||||
|
||||
_ = enc.SetMaxBandwidth(opus.Fullband)
|
||||
_ = enc.SetMaxBandwidth(FullBand)
|
||||
_ = enc.SetBitrate(192000)
|
||||
_ = enc.SetComplexity(10)
|
||||
|
||||
|
|
@ -92,7 +90,7 @@ func (e *Encoder) Encode(pcm []int16) ([]byte, error) {
|
|||
pcm = resampleFn(pcm, e.resampleBufSize)
|
||||
}
|
||||
data := make([]byte, e.outBufferSize)
|
||||
n, err := e.Encoder.Encode(pcm, data)
|
||||
n, err := e.LibOpusEncoder.Encode(pcm, data)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
|
@ -100,16 +98,16 @@ func (e *Encoder) Encode(pcm []int16) ([]byte, error) {
|
|||
}
|
||||
|
||||
func (e *Encoder) GetInfo() string {
|
||||
bitrate, _ := e.Encoder.Bitrate()
|
||||
complexity, _ := e.Encoder.Complexity()
|
||||
dtx, _ := e.Encoder.DTX()
|
||||
fec, _ := e.Encoder.InBandFEC()
|
||||
maxBandwidth, _ := e.Encoder.MaxBandwidth()
|
||||
lossPercent, _ := e.Encoder.PacketLossPerc()
|
||||
sampleRate, _ := e.Encoder.SampleRate()
|
||||
bitrate, _ := e.LibOpusEncoder.Bitrate()
|
||||
complexity, _ := e.LibOpusEncoder.Complexity()
|
||||
dtx, _ := e.LibOpusEncoder.DTX()
|
||||
fec, _ := e.LibOpusEncoder.FEC()
|
||||
maxBandwidth, _ := e.LibOpusEncoder.MaxBandwidth()
|
||||
lossPercent, _ := e.LibOpusEncoder.PacketLossPerc()
|
||||
sampleRate, _ := e.LibOpusEncoder.SampleRate()
|
||||
return fmt.Sprintf(
|
||||
"Bitrate: %v bps, Complexity: %v, DTX: %v, FEC: %v, Max bandwidth: *%v, Loss%%: %v, Rate: %v Hz",
|
||||
bitrate, complexity, dtx, fec, maxBandwidth, lossPercent, sampleRate,
|
||||
"%v, Bitrate: %v bps, Complexity: %v, DTX: %v, FEC: %v, Max bandwidth: *%v, Loss%%: %v, Rate: %v Hz",
|
||||
CodecVersion(), bitrate, complexity, dtx, fec, maxBandwidth, lossPercent, sampleRate,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
199
pkg/encoder/opus/opus.go
Normal file
199
pkg/encoder/opus/opus.go
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
package opus
|
||||
|
||||
/*
|
||||
#cgo pkg-config: opus
|
||||
|
||||
#include <opus.h>
|
||||
|
||||
int bridge_encoder_get_bitrate(OpusEncoder *st, opus_int32 *bitrate) { return opus_encoder_ctl(st, OPUS_GET_BITRATE(bitrate)); }
|
||||
int bridge_encoder_get_complexity(OpusEncoder *st, opus_int32 *complexity) { return opus_encoder_ctl(st, OPUS_GET_COMPLEXITY(complexity)); }
|
||||
int bridge_encoder_get_dtx(OpusEncoder *st, opus_int32 *dtx) { return opus_encoder_ctl(st, OPUS_GET_DTX(dtx)); }
|
||||
int bridge_encoder_get_inband_fec(OpusEncoder *st, opus_int32 *fec) { return opus_encoder_ctl(st, OPUS_GET_INBAND_FEC(fec)); }
|
||||
int bridge_encoder_get_max_bandwidth(OpusEncoder *st, opus_int32 *max_bw) { return opus_encoder_ctl(st, OPUS_GET_MAX_BANDWIDTH(max_bw)); }
|
||||
int bridge_encoder_get_packet_loss_perc(OpusEncoder *st, opus_int32 *loss_perc) { return opus_encoder_ctl(st, OPUS_GET_PACKET_LOSS_PERC(loss_perc)); }
|
||||
int bridge_encoder_get_sample_rate(OpusEncoder *st, opus_int32 *sample_rate) { return opus_encoder_ctl(st, OPUS_GET_SAMPLE_RATE(sample_rate)); }
|
||||
int bridge_encoder_set_bitrate(OpusEncoder *st, opus_int32 bitrate) { return opus_encoder_ctl(st, OPUS_SET_BITRATE(bitrate)); }
|
||||
int bridge_encoder_set_complexity(OpusEncoder *st, opus_int32 complexity) { return opus_encoder_ctl(st, OPUS_SET_COMPLEXITY(complexity)); }
|
||||
int bridge_encoder_set_dtx(OpusEncoder *st, opus_int32 use_dtx) { return opus_encoder_ctl(st, OPUS_SET_DTX(use_dtx)); }
|
||||
int bridge_encoder_set_inband_fec(OpusEncoder *st, opus_int32 fec) { return opus_encoder_ctl(st, OPUS_SET_INBAND_FEC(fec)); }
|
||||
int bridge_encoder_set_max_bandwidth(OpusEncoder *st, opus_int32 max_bw) { return opus_encoder_ctl(st, OPUS_SET_MAX_BANDWIDTH(max_bw)); }
|
||||
int bridge_encoder_set_packet_loss_perc(OpusEncoder *st, opus_int32 loss_perc) { return opus_encoder_ctl(st, OPUS_SET_PACKET_LOSS_PERC(loss_perc)); }
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type (
|
||||
Application int
|
||||
Bandwidth int
|
||||
Bitrate int
|
||||
Error int
|
||||
)
|
||||
|
||||
const (
|
||||
// Optimize encoding for VoIP
|
||||
AppVoIP = Application(C.OPUS_APPLICATION_VOIP)
|
||||
// Optimize encoding for non-voice signals like music
|
||||
AppAudio = Application(C.OPUS_APPLICATION_AUDIO)
|
||||
// Optimize encoding for low latency applications
|
||||
AppRestrictedLowdelay = Application(C.OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
|
||||
// Auto/default setting
|
||||
BitrateAuto = Bitrate(-1000)
|
||||
BitrateMax = Bitrate(-1)
|
||||
|
||||
// 20 kHz bandpass
|
||||
FullBand = Bandwidth(C.OPUS_BANDWIDTH_FULLBAND)
|
||||
)
|
||||
|
||||
const (
|
||||
ErrorOK = Error(C.OPUS_OK)
|
||||
ErrorBadArg = Error(C.OPUS_BAD_ARG)
|
||||
ErrorBufferTooSmall = Error(C.OPUS_BUFFER_TOO_SMALL)
|
||||
ErrorInternalError = Error(C.OPUS_INTERNAL_ERROR)
|
||||
ErrorInvalidPacket = Error(C.OPUS_INVALID_PACKET)
|
||||
ErrorUnimplemented = Error(C.OPUS_UNIMPLEMENTED)
|
||||
ErrorInvalidState = Error(C.OPUS_INVALID_STATE)
|
||||
ErrorAllocFail = Error(C.OPUS_ALLOC_FAIL)
|
||||
)
|
||||
|
||||
type LibOpusEncoder struct {
|
||||
buf []byte
|
||||
channels int
|
||||
ptr *C.struct_OpusEncoder
|
||||
}
|
||||
|
||||
// NewOpusEncoder creates new Opus encoder.
|
||||
func NewOpusEncoder(sampleRate int, channels int, app Application) (*LibOpusEncoder, error) {
|
||||
var enc LibOpusEncoder
|
||||
if enc.ptr != nil {
|
||||
return nil, fmt.Errorf("opus: encoder reinit")
|
||||
}
|
||||
enc.channels = channels
|
||||
// !to check mem leak
|
||||
enc.buf = make([]byte, C.opus_encoder_get_size(C.int(channels)))
|
||||
enc.ptr = (*C.OpusEncoder)(unsafe.Pointer(&enc.buf[0]))
|
||||
err := unwrap(C.opus_encoder_init(enc.ptr, C.opus_int32(sampleRate), C.int(channels), C.int(app)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("opus: initializatoin error (%v)", err)
|
||||
}
|
||||
return &enc, nil
|
||||
}
|
||||
|
||||
// Encode converts raw PCM samples into the supplied Opus buffer.
|
||||
// Returns the number of bytes converted.
|
||||
func (enc *LibOpusEncoder) Encode(pcm []int16, data []byte) (rez int, err error) {
|
||||
if len(pcm) == 0 {
|
||||
return
|
||||
}
|
||||
samples := C.int(len(pcm) / enc.channels)
|
||||
n := C.opus_encode(enc.ptr, (*C.opus_int16)(&pcm[0]), samples, (*C.uchar)(&data[0]), C.opus_int32(cap(data)))
|
||||
if n > 0 {
|
||||
rez = int(n)
|
||||
}
|
||||
return rez, unwrap(n)
|
||||
}
|
||||
|
||||
// SampleRate returns the sample rate of the encoder.
|
||||
func (enc *LibOpusEncoder) SampleRate() (int, error) {
|
||||
var sampleRate C.opus_int32
|
||||
res := C.bridge_encoder_get_sample_rate(enc.ptr, &sampleRate)
|
||||
return int(sampleRate), unwrap(res)
|
||||
}
|
||||
|
||||
// Bitrate returns the bitrate of the encoder.
|
||||
func (enc *LibOpusEncoder) Bitrate() (int, error) {
|
||||
var bitrate C.opus_int32
|
||||
res := C.bridge_encoder_get_bitrate(enc.ptr, &bitrate)
|
||||
return int(bitrate), unwrap(res)
|
||||
}
|
||||
|
||||
// SetBitrate sets the bitrate of the encoder.
|
||||
// BitrateMax / BitrateAuto can be used here.
|
||||
func (enc *LibOpusEncoder) SetBitrate(b Bitrate) error {
|
||||
return unwrap(C.bridge_encoder_set_bitrate(enc.ptr, C.opus_int32(b)))
|
||||
}
|
||||
|
||||
// Complexity returns the value of the complexity.
|
||||
func (enc *LibOpusEncoder) Complexity() (int, error) {
|
||||
var complexity C.opus_int32
|
||||
res := C.bridge_encoder_get_complexity(enc.ptr, &complexity)
|
||||
return int(complexity), unwrap(res)
|
||||
}
|
||||
|
||||
// SetComplexity sets the complexity factor for the encoder.
|
||||
// Complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest.
|
||||
func (enc *LibOpusEncoder) SetComplexity(complexity int) error {
|
||||
return unwrap(C.bridge_encoder_set_complexity(enc.ptr, C.opus_int32(complexity)))
|
||||
}
|
||||
|
||||
// DTX says if discontinuous transmission is enabled.
|
||||
func (enc *LibOpusEncoder) DTX() (bool, error) {
|
||||
var dtx C.opus_int32
|
||||
res := C.bridge_encoder_get_dtx(enc.ptr, &dtx)
|
||||
return dtx > 0, unwrap(res)
|
||||
}
|
||||
|
||||
// SetDTX switches discontinuous transmission.
|
||||
func (enc *LibOpusEncoder) SetDTX(dtx bool) error {
|
||||
var i int
|
||||
if dtx {
|
||||
i = 1
|
||||
}
|
||||
return unwrap(C.bridge_encoder_set_dtx(enc.ptr, C.opus_int32(i)))
|
||||
}
|
||||
|
||||
// MaxBandwidth returns the maximum allowed bandpass value.
|
||||
func (enc *LibOpusEncoder) MaxBandwidth() (Bandwidth, error) {
|
||||
var b C.opus_int32
|
||||
res := C.bridge_encoder_get_max_bandwidth(enc.ptr, &b)
|
||||
return Bandwidth(b), unwrap(res)
|
||||
}
|
||||
|
||||
// SetMaxBandwidth sets the upper limit of the bandpass.
|
||||
func (enc *LibOpusEncoder) SetMaxBandwidth(b Bandwidth) error {
|
||||
return unwrap(C.bridge_encoder_set_max_bandwidth(enc.ptr, C.opus_int32(b)))
|
||||
}
|
||||
|
||||
// FEC says if forward error correction (FEC) is enabled.
|
||||
func (enc *LibOpusEncoder) FEC() (bool, error) {
|
||||
var fec C.opus_int32
|
||||
res := C.bridge_encoder_get_inband_fec(enc.ptr, &fec)
|
||||
return fec > 0, unwrap(res)
|
||||
}
|
||||
|
||||
// SetFEC switches the forward error correction (FEC).
|
||||
func (enc *LibOpusEncoder) SetFEC(fec bool) error {
|
||||
var i int
|
||||
if fec {
|
||||
i = 1
|
||||
}
|
||||
return unwrap(C.bridge_encoder_set_inband_fec(enc.ptr, C.opus_int32(i)))
|
||||
}
|
||||
|
||||
// PacketLossPerc returns configured packet loss percentage.
|
||||
func (enc *LibOpusEncoder) PacketLossPerc() (int, error) {
|
||||
var lossPerc C.opus_int32
|
||||
res := C.bridge_encoder_get_packet_loss_perc(enc.ptr, &lossPerc)
|
||||
return int(lossPerc), unwrap(res)
|
||||
}
|
||||
|
||||
// SetPacketLossPerc sets expected packet loss percentage.
|
||||
func (enc *LibOpusEncoder) SetPacketLossPerc(lossPerc int) error {
|
||||
return unwrap(C.bridge_encoder_set_packet_loss_perc(enc.ptr, C.opus_int32(lossPerc)))
|
||||
}
|
||||
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprintf("opus: %v", C.GoString(C.opus_strerror(C.int(e))))
|
||||
}
|
||||
|
||||
func unwrap(error C.int) (err error) {
|
||||
if error < C.OPUS_OK {
|
||||
err = Error(int(error))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CodecVersion() string { return C.GoString(C.opus_get_version_string()) }
|
||||
|
|
@ -6,8 +6,8 @@ type Env string
|
|||
|
||||
const (
|
||||
Dev Env = "dev"
|
||||
Staging = "staging"
|
||||
Production = "prod"
|
||||
Staging Env = "staging"
|
||||
Production Env = "prod"
|
||||
)
|
||||
|
||||
func (env *Env) AnyOf(what ...Env) bool {
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
// credit to https://github.com/poi5305/go-yuv2webRTC/blob/master/webrtc/webrtc.go
|
||||
package webrtc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func zip(in []byte) []byte {
|
||||
var b bytes.Buffer
|
||||
gz := gzip.NewWriter(&b)
|
||||
_, err := gz.Write(in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = gz.Flush()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = gz.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func unzip(in []byte) []byte {
|
||||
var b bytes.Buffer
|
||||
_, err := b.Write(in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
r, err := gzip.NewReader(&b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
res, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
@ -31,7 +31,6 @@ type WebRTC struct {
|
|||
cfg webrtcConfig.Config
|
||||
tsInterceptor itc.ReTime
|
||||
isConnected bool
|
||||
isClosed bool
|
||||
// for yuvI420 image
|
||||
ImageChannel chan WebFrame
|
||||
AudioChannel chan []byte
|
||||
|
|
@ -39,9 +38,9 @@ type WebRTC struct {
|
|||
//VoiceOutChannel chan []byte
|
||||
InputChannel chan []byte
|
||||
|
||||
Done bool
|
||||
lastTime time.Time
|
||||
curFPS int
|
||||
Done bool
|
||||
//lastTime time.Time
|
||||
//curFPS int
|
||||
|
||||
RoomID string
|
||||
|
||||
|
|
@ -152,6 +151,9 @@ func (w *WebRTC) StartClient(isMobile bool, iceCB OnIceCallback) (string, error)
|
|||
// create data channel for input, and register callbacks
|
||||
// order: true, negotiated: false, id: random
|
||||
inputTrack, err := w.connection.CreateDataChannel("game-input", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
inputTrack.OnOpen(func() {
|
||||
log.Printf("Data channel '%s'-'%d' open.\n", inputTrack.Label(), inputTrack.ID())
|
||||
|
|
@ -295,7 +297,7 @@ func (w *WebRTC) AddCandidate(candidate string) error {
|
|||
// StopClient disconnect
|
||||
func (w *WebRTC) StopClient() {
|
||||
// if stopped, bypass
|
||||
if w.isConnected == false {
|
||||
if !w.isConnected {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -382,10 +384,10 @@ func (w *WebRTC) startStreaming(vp8Track *webrtc.TrackLocalStaticSample, opusTra
|
|||
//}()
|
||||
}
|
||||
|
||||
func (w *WebRTC) calculateFPS() int {
|
||||
elapsedTime := time.Now().Sub(w.lastTime)
|
||||
w.lastTime = time.Now()
|
||||
curFPS := time.Second / elapsedTime
|
||||
w.curFPS = int(float32(w.curFPS)*0.9 + float32(curFPS)*0.1)
|
||||
return w.curFPS
|
||||
}
|
||||
//func (w *WebRTC) calculateFPS() int {
|
||||
// elapsedTime := time.Now().Sub(w.lastTime)
|
||||
// w.lastTime = time.Now()
|
||||
// curFPS := time.Second / elapsedTime
|
||||
// w.curFPS = int(float32(w.curFPS)*0.9 + float32(curFPS)*0.1)
|
||||
// return w.curFPS
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,12 @@ func (h *Handler) Prepare() {
|
|||
|
||||
log.Printf("Starting Libretro cores sync...")
|
||||
coreManager := remotehttp.NewRemoteHttpManager(h.cfg.Emulator.Libretro)
|
||||
// make a dir for cores
|
||||
dir := coreManager.Conf.GetCoresStorePath()
|
||||
if err := os.MkdirAll(dir, os.ModeDir); err != nil {
|
||||
log.Printf("error: couldn't make %v directory", dir)
|
||||
return
|
||||
}
|
||||
if err := coreManager.Sync(); err != nil {
|
||||
log.Printf("error: cores sync has failed, %v", err)
|
||||
}
|
||||
|
|
|
|||
17
scripts/install.sh
vendored
Executable file
17
scripts/install.sh
vendored
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
echo This script should install application dependencies for Debian-based systems
|
||||
if [ $(id -u) -ne 0 ]
|
||||
then
|
||||
echo "error: run with sudo or root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y \
|
||||
libvpx6 \
|
||||
libx264-160 \
|
||||
libopus0 \
|
||||
libsdl2-2.0-0 \
|
||||
libgl1-mesa-glx \
|
||||
xvfb
|
||||
Loading…
Add table
Add a link
Reference in a new issue