Merge pull request #4379 from 21pages/av1

av1 support
This commit is contained in:
RustDesk 2023-05-21 18:44:40 +08:00 committed by GitHub
commit f26bdda977
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 968 additions and 337 deletions

View File

@ -94,11 +94,11 @@ jobs:
uses: lukka/run-vcpkg@v7
with:
setupOnly: true
vcpkgGitCommitId: '1d4128f08e30cec31b94500840c7eca8ebc579cb'
vcpkgGitCommitId: '501db0f17ef6df184fcdbfbe0f87cde2313b6ab1' #2023.04.15
- name: Install vcpkg dependencies
run: |
$VCPKG_ROOT/vcpkg install libvpx libyuv opus
$VCPKG_ROOT/vcpkg install libvpx libyuv opus aom
shell: bash
- name: Install Rust toolchain

View File

@ -11,9 +11,9 @@ env:
LLVM_VERSION: "15.0.6"
FLUTTER_VERSION: "3.7.0"
TAG_NAME: "nightly"
# vcpkg version: 2022.05.10
# vcpkg version: 2023.04.15
# for multiarch gcc compatibility
VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44"
VCPKG_COMMIT_ID: "501db0f17ef6df184fcdbfbe0f87cde2313b6ab1"
VERSION: "1.2.0"
NDK_VERSION: "r23"
#signing keys env variable checks
@ -319,7 +319,7 @@ jobs:
- name: Install vcpkg dependencies
run: |
$VCPKG_ROOT/vcpkg install libvpx libyuv opus
$VCPKG_ROOT/vcpkg install libvpx libyuv opus aom
- name: Show version information (Rust, cargo, Clang)
shell: bash

View File

@ -63,7 +63,7 @@ jobs:
pushd vcpkg
git reset --hard ${{ env.VCPKG_COMMIT_ID }}
./bootstrap-vcpkg.sh
./vcpkg install libvpx libyuv opus
./vcpkg install libvpx libyuv opus aom
;;
aarch64)
pushd /artifacts

View File

@ -65,8 +65,8 @@ Please download Sciter dynamic library yourself.
- Install [vcpkg](https://github.com/microsoft/vcpkg), and set `VCPKG_ROOT` env variable correctly
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/macOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/macOS: vcpkg install libvpx libyuv opus aom
- run `cargo run`
@ -104,11 +104,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Fix libvpx (For Fedora)

View File

@ -55,8 +55,8 @@
- بطريقة صحيحة `VCPKG_ROOT` env variable وأعد [vcpkg](https://github.com/microsoft/vcpkg) ثبت
- Windows: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static`
- Linux/MacOS: `vcpkg install libvpx libyuv opus`
- Windows: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static`
- Linux/MacOS: `vcpkg install libvpx libyuv opus aom`
- run `cargo run`
@ -88,11 +88,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Fix libvpx (For Fedora)

View File

@ -49,8 +49,8 @@ Varianta pro mobilní platformy používá aplikační rámec (framework) Flutte
- Nainstalujte [vcpkg](https://github.com/microsoft/vcpkg), a nastavte správně proměnnou prostsředí `VCPKG_ROOT`
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- spusťte `cargo run`
@ -81,11 +81,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Oprava libvpx (pro Fedoru)

View File

@ -47,8 +47,8 @@ Hent venligst sciter dynamic library selv.
- Installer [vcpkg](https://github.com/microsoft/vcpkg), og indstil env-variabelen "VCPKG_ROOT" korrekt
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- kør `cargo run`
@ -79,11 +79,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### libvpx rettelse (For Fedora)

View File

@ -65,8 +65,8 @@ Bitte laden Sie die dynamische Bibliothek Sciter selbst herunter.
- Installieren Sie [vcpkg](https://github.com/microsoft/vcpkg) und fügen Sie die Systemumgebungsvariable `VCPKG_ROOT` hinzu
- Windows: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static`
- Linux/macOS: `vcpkg install libvpx libyuv opus`
- Windows: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static`
- Linux/macOS: `vcpkg install libvpx libyuv opus aom`
- Nutzen Sie `cargo run`
@ -104,11 +104,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### libvpx reparieren (für Fedora)

View File

@ -45,8 +45,8 @@ La labortabla versio uzas [sciter](https://sciter.com/) por la interfaco, bonvol
- Instalu [vcpkg](https://github.com/microsoft/vcpkg), kaj agordu la medivariablon `VCPKG_ROOT` korekte
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Plenumu `cargo run`
@ -75,11 +75,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Ripari libvpx (Por Fedora)

View File

@ -54,8 +54,8 @@ Por favor descarga la librería dinámica de Sciter tu mismo.
- Instala [vcpkg](https://github.com/microsoft/vcpkg), y configura la variable de entono `VCPKG_ROOT` correctamente.
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/Osx: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/Osx: vcpkg install libvpx libyuv opus aom
- Corre `cargo run`
@ -84,11 +84,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Arregla libvpx (Para Fedora)

View File

@ -52,8 +52,8 @@
- نرم افزار [vcpkg](https://github.com/microsoft/vcpkg) را نصب کنید و متغیر `VCPKG_ROOT` را به درستی تنظیم کنید.
- بسته‌های vcpkg مورد نیاز را نصب کنید:
- ویندوز: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static`
- مک و لینوکس: `vcpkg install libvpx libyuv opus`
- ویندوز: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static`
- مک و لینوکس: `vcpkg install libvpx libyuv opus aom`
- این دستور را اجرا کنید: `cargo run`
## [ساخت](https://rustdesk.com/docs/en/dev/build/)
@ -83,11 +83,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### رفع ایراد libvpx (برای فدورا)

View File

@ -45,8 +45,8 @@ Desktop-versiot käyttävät [sciter](https://sciter.com/) graafisena käyttöli
- Asenna [vcpkg](https://github.com/microsoft/vcpkg), ja aseta `VCPKG_ROOT`-ympäristömuuttuja oikein
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- suorita `cargo run`
@ -75,11 +75,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Korjaa libvpx (Fedora)

View File

@ -45,8 +45,8 @@ Les versions de bureau utilisent [sciter](https://sciter.com/) pour l'interface
- Installez [vcpkg](https://github.com/microsoft/vcpkg), et définissez correctement la variable d'environnement `VCPKG_ROOT`.
- Windows : vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/Osx : vcpkg install libvpx libyuv opus
- Windows : vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/Osx : vcpkg install libvpx libyuv opus aom
- Exécuter `cargo run`
@ -75,11 +75,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Corriger libvpx (Pour Fedora)

View File

@ -65,8 +65,8 @@
- Εγκαταστήσετε το [vcpkg](https://github.com/microsoft/vcpkg), και ρυθμίστε σωστά την παράμετρο συστήματος `VCPKG_ROOT`
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Εκτελέστε `cargo run`
@ -104,11 +104,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Διόρθωση libvpx (για Fedora)

View File

@ -55,8 +55,8 @@ A telefonos verziók Flutter-t hasznának. Később lehetséges hogy Sciterről
- Telepítsd a [vcpkg](https://github.com/microsoft/vcpkg)-t, és állítsd be a `VCPKG_ROOT` környezeti változót helyesen
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Futtasd a `cargo run` parancsot
@ -87,11 +87,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Fixeld a libvpx-t (Fedora-n csak)

View File

@ -45,8 +45,8 @@ Versi desktop menggunakan [sciter](https://sciter.com/) untuk GUI, silahkan down
- Install [vcpkg](https://github.com/microsoft/vcpkg), dan arahkan `VCPKG_ROOT` env variable dengan benar
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- jalankan `cargo run`
@ -75,11 +75,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Perbaiki libvpx (Untuk Fedora)

View File

@ -45,8 +45,8 @@ La versione Desktop utilizza [sciter](https://sciter.com/) per la GUI, per favor
- Installa [vcpkg](https://github.com/microsoft/vcpkg), e imposta correttamente la variabile d'ambiente `VCPKG_ROOT`
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Esegui `cargo run`
@ -75,11 +75,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Fix libvpx (Per Fedora)

View File

@ -51,8 +51,8 @@ RustDeskは誰からの貢献も歓迎します。 貢献するには [`docs/CON
- [vcpkg](https://github.com/microsoft/vcpkg), をインストールし、 `VCPKG_ROOT` 環境変数を正しく設定します。
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- run `cargo run`
@ -85,11 +85,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Fix libvpx (For Fedora)

View File

@ -51,8 +51,8 @@ RustDesk는 모든 기여를 환영합니다. 기여하고자 한다면 [`docs/C
- [vcpkg](https://github.com/microsoft/vcpkg) 설치하고 `VCPKG_ROOT` 환경변수를 정확히 설정합니다.
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- run `cargo run`
@ -83,11 +83,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Fix libvpx (For Fedora)

View File

@ -44,8 +44,8 @@
- [vcpkg](https://github.com/microsoft/vcpkg) ഇൻസ്റ്റാൾ ചെയ്ത് `VCPKG_ROOT` env വേരിയബിൾ ശരിയായി സജ്ജമാക്കുക
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- run `cargo run`
@ -74,11 +74,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### libvpx പരിഹരിക്കുക (ഫെഡോറയ്ക്ക്)

View File

@ -63,8 +63,8 @@ Download zelf de dynamic library van Sciter.
- Installeer [vcpkg](https://github.com/microsoft/vcpkg) en configureer de `VCPKG_ROOT` omgevingsvariabele op de juiste manier:
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Voer uit: `cargo run`
@ -101,11 +101,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Fix voor libvpx (voor Fedora)

View File

@ -63,8 +63,8 @@ Wersje desktopowe używają [sciter](https://sciter.com/) dla GUI, proszę pobra
- Zainstaluj [vcpkg](https://github.com/microsoft/vcpkg), i ustaw prawidłowo zmienną `VCPKG_ROOT`
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- uruchom `cargo run`
@ -99,11 +99,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Popraw libvpx (Dla Fedora)

View File

@ -45,8 +45,8 @@ Versões de desktop utilizam [sciter](https://sciter.com/) para a GUI, por favor
- Instale [vcpkg](https://github.com/microsoft/vcpkg), e configure a variável de ambiente `VCPKG_ROOT` corretamente
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Execute `cargo run`
@ -75,11 +75,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Conserte libvpx (Para o Fedora)

View File

@ -57,8 +57,8 @@ RustDesk приветствует вклад каждого. Ознакомьт
- Установите [vcpkg](https://github.com/microsoft/vcpkg), и правильно установите переменную `VCPKG_ROOT`
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Запустите `cargo run`
@ -87,11 +87,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Исправление libvpx (для Fedora)

View File

@ -67,8 +67,8 @@ RustDesk вітає внесок кожного. Дивіться [`docs/CONTRIB
- Встановіть [vcpkg](https://github.com/microsoft/vcpkg), і правильно встановіть змінну `VCPKG_ROOT`.
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Запустіть `cargo run`
@ -104,11 +104,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ...
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Виправлення libvpx (для Fedora)

View File

@ -55,8 +55,8 @@ Phiên bản cho điện thoại sử dụng Flutter. Chúng tôi sẽ chuyển
- Tải và cài [vcpkg](https://github.com/microsoft/vcpkg), và đặt biến môi trường `VCPKG_ROOT` sao cho đúng.
- Đối với Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Đối với Linux/MacOS: vcpkg install libvpx libyuv opus
- Đối với Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Đối với Linux/MacOS: vcpkg install libvpx libyuv opus aom
- Chạy lệnh `cargo run`
@ -87,11 +87,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### Cách sửa lỗi libvpx (Dành cho hệ điều hành Fedora)

View File

@ -48,8 +48,8 @@ Chat with us: [知乎](https://www.zhihu.com/people/rustdesk) | [Discord](https:
- 安装[vcpkg](https://github.com/microsoft/vcpkg), 正确设置`VCPKG_ROOT`环境变量
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
- Linux/Osx: vcpkg install libvpx libyuv opus
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
- Linux/Osx: vcpkg install libvpx libyuv opus aom
- 运行 `cargo run`
@ -80,11 +80,11 @@ sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-c
```sh
git clone https://github.com/microsoft/vcpkg
cd vcpkg
git checkout 2021.12.01
git checkout 2023.04.15
cd ..
vcpkg/bootstrap-vcpkg.sh
export VCPKG_ROOT=$HOME/vcpkg
vcpkg/vcpkg install libvpx libyuv opus
vcpkg/vcpkg install libvpx libyuv opus aom
```
### 修复 libvpx (仅仅针对 Fedora)

View File

@ -280,15 +280,18 @@ Future<List<TRadioMenu<String>>> toolbarCodec(
try {
final Map codecsJson = jsonDecode(alternativeCodecs);
final vp8 = codecsJson['vp8'] ?? false;
final av1 = codecsJson['av1'] ?? false;
final h264 = codecsJson['h264'] ?? false;
final h265 = codecsJson['h265'] ?? false;
codecs.add(vp8);
codecs.add(av1);
codecs.add(h264);
codecs.add(h265);
} catch (e) {
debugPrint("Show Codec Preference err=$e");
}
final visible = codecs.length == 3 && (codecs[0] || codecs[1] || codecs[2]);
final visible =
codecs.length == 4 && (codecs[0] || codecs[1] || codecs[2] || codecs[3]);
if (!visible) return [];
onChanged(String? value) async {
if (value == null) return;
@ -307,10 +310,11 @@ Future<List<TRadioMenu<String>>> toolbarCodec(
return [
radio('Auto', 'auto', true),
if (isDesktop || codecs[0]) radio('VP8', 'vp8', codecs[0]),
if (codecs[0]) radio('VP8', 'vp8', codecs[0]),
radio('VP9', 'vp9', true),
if (isDesktop || codecs[1]) radio('H264', 'h264', codecs[1]),
if (isDesktop || codecs[2]) radio('H265', 'h265', codecs[2]),
if (codecs[1]) radio('AV1', 'av1', codecs[1]),
if (codecs[2]) radio('H264', 'h264', codecs[2]),
if (codecs[3]) radio('H265', 'h265', codecs[3]),
];
}

View File

@ -1322,6 +1322,11 @@ class _DisplayState extends State<_Display> {
groupValue: groupValue,
label: 'VP9',
onChanged: onChanged),
_Radio(context,
value: 'av1',
groupValue: groupValue,
label: 'AV1',
onChanged: onChanged),
...hwRadios,
]);
}

View File

@ -25,6 +25,7 @@ message VideoFrame {
EncodedVideoFrames h264s = 10;
EncodedVideoFrames h265s = 11;
EncodedVideoFrames vp8s = 12;
EncodedVideoFrames av1s = 13;
}
}
@ -85,6 +86,7 @@ message SupportedEncoding {
bool h264 = 1;
bool h265 = 2;
bool vp8 = 3;
bool av1 = 4;
}
message PeerInfo {
@ -477,6 +479,7 @@ message SupportedDecoding {
H264 = 2;
H265 = 3;
VP8 = 4;
AV1 = 5;
}
int32 ability_vp9 = 1;
@ -484,6 +487,7 @@ message SupportedDecoding {
int32 ability_h265 = 3;
PreferCodec prefer = 4;
int32 ability_vp8 = 5;
int32 ability_av1 = 6;
}
message OptionMessage {

View File

@ -1399,7 +1399,9 @@ impl UserDefaultConfig {
"view_style" => self.get_string(key, "original", vec!["adaptive"]),
"scroll_style" => self.get_string(key, "scrollauto", vec!["scrollbar"]),
"image_quality" => self.get_string(key, "balanced", vec!["best", "low", "custom"]),
"codec-preference" => self.get_string(key, "auto", vec!["vp8", "vp9", "h264", "h265"]),
"codec-preference" => {
self.get_string(key, "auto", vec!["vp8", "vp9", "av1", "h264", "h265"])
}
"custom_image_quality" => self.get_double_string(key, 50.0, 10.0, 100.0),
"custom-fps" => self.get_double_string(key, 30.0, 5.0, 120.0),
_ => self

View File

@ -128,9 +128,9 @@ fn find_package(name: &str) -> Vec<PathBuf> {
let no_pkg_config_var_name = format!("NO_PKG_CONFIG_{name}");
println!("cargo:rerun-if-env-changed={no_pkg_config_var_name}");
if cfg!(all(target_os = "linux", feature = "linux-pkg-config"))
&& std::env::var(no_pkg_config_var_name).as_deref() != Ok("1") {
link_pkg_config(name)
&& std::env::var(no_pkg_config_var_name).as_deref() != Ok("1")
{
link_pkg_config(name)
} else if let Ok(vcpkg_root) = std::env::var("VCPKG_ROOT") {
vec![link_vcpkg(vcpkg_root.into(), name)]
} else {
@ -144,16 +144,17 @@ fn generate_bindings(
include_paths: &[PathBuf],
ffi_rs: &Path,
exact_file: &Path,
regex: &str,
) {
let mut b = bindgen::builder()
.header(ffi_header.to_str().unwrap())
.allowlist_type("^[vV].*")
.allowlist_var("^[vV].*")
.allowlist_function("^[vV].*")
.rustified_enum("^v.*")
.allowlist_type(regex)
.allowlist_var(regex)
.allowlist_function(regex)
.rustified_enum(regex)
.trust_clang_mangling(false)
.layout_tests(false) // breaks 32/64-bit compat
.generate_comments(false); // vpx comments have prefix /*!\
.generate_comments(false); // comments have prefix /*!\
for dir in include_paths {
b = b.clang_arg(format!("-I{}", dir.display()));
@ -163,22 +164,22 @@ fn generate_bindings(
fs::copy(ffi_rs, exact_file).ok(); // ignore failure
}
fn gen_vpx() {
let includes = find_package("libvpx");
fn gen_vcpkg_package(package: &str, ffi_header: &str, generated: &str, regex: &str) {
let includes = find_package(package);
let src_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
let src_dir = Path::new(&src_dir);
let out_dir = env::var_os("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir);
let ffi_header = src_dir.join("vpx_ffi.h");
let ffi_header = src_dir.join("src").join("bindings").join(ffi_header);
println!("rerun-if-changed={}", ffi_header.display());
for dir in &includes {
println!("rerun-if-changed={}", dir.display());
}
let ffi_rs = out_dir.join("vpx_ffi.rs");
let exact_file = src_dir.join("generated").join("vpx_ffi.rs");
generate_bindings(&ffi_header, &includes, &ffi_rs, &exact_file);
let ffi_rs = out_dir.join(generated);
let exact_file = src_dir.join("generated").join(generated);
generate_bindings(&ffi_header, &includes, &ffi_rs, &exact_file, regex);
}
fn main() {
@ -194,7 +195,8 @@ fn main() {
env::set_var("CARGO_CFG_TARGET_FEATURE", "crt-static");
find_package("libyuv");
gen_vpx();
gen_vcpkg_package("libvpx", "vpx_ffi.h", "vpx_ffi.rs", "^[vV].*");
gen_vcpkg_package("aom", "aom_ffi.h", "aom_ffi.rs", "^(aom|AOM|OBU|AV1).*");
// there is problem with cfg(target_os) in build.rs, so use our workaround
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();

View File

@ -1,6 +1,7 @@
use docopt::Docopt;
use hbb_common::env_logger::{init_from_env, Env, DEFAULT_FILTER_ENV};
use scrap::{
aom::{AomDecoder, AomDecoderConfig, AomEncoder, AomEncoderConfig},
codec::{EncoderApi, EncoderCfg},
Capturer, Display, TraitCapturer, VpxDecoder, VpxDecoderConfig, VpxEncoder, VpxEncoderConfig,
VpxVideoCodecId::{self, *},
@ -51,6 +52,7 @@ fn main() {
width, height, bitrate_k, args.flag_hw_pixfmt
);
[VP8, VP9].map(|c| test_vpx(c, &yuvs, width, height, bitrate_k, yuv_count));
test_av1(&yuvs, width, height, bitrate_k, yuv_count);
#[cfg(feature = "hwcodec")]
{
use hwcodec::AVPixelFormat;
@ -105,34 +107,29 @@ fn test_vpx(
num_threads: (num_cpus::get() / 2) as _,
});
let mut encoder = VpxEncoder::new(config).unwrap();
let start = Instant::now();
for yuv in yuvs {
let _ = encoder
.encode(start.elapsed().as_millis() as _, yuv, STRIDE_ALIGN)
.unwrap();
let _ = encoder.flush().unwrap();
}
println!(
"{:?} encode: {:?}",
codec_id,
start.elapsed() / yuv_count as _
);
// prepare data separately
let mut vpxs = vec![];
let start = Instant::now();
let mut size = 0;
for yuv in yuvs {
for ref frame in encoder
.encode(start.elapsed().as_millis() as _, yuv, STRIDE_ALIGN)
.unwrap()
{
size += frame.data.len();
vpxs.push(frame.data.to_vec());
}
for ref frame in encoder.flush().unwrap() {
size += frame.data.len();
vpxs.push(frame.data.to_vec());
}
}
assert_eq!(vpxs.len(), yuv_count);
println!(
"{:?} encode: {:?}, {} byte",
codec_id,
start.elapsed() / yuv_count as _,
size / yuv_count
);
let mut decoder = VpxDecoder::new(VpxDecoderConfig {
codec: codec_id,
@ -151,6 +148,43 @@ fn test_vpx(
);
}
fn test_av1(yuvs: &Vec<Vec<u8>>, width: usize, height: usize, bitrate_k: usize, yuv_count: usize) {
let config = EncoderCfg::AOM(AomEncoderConfig {
width: width as _,
height: height as _,
bitrate: bitrate_k as _,
});
let mut encoder = AomEncoder::new(config).unwrap();
let start = Instant::now();
let mut size = 0;
let mut av1s = vec![];
for yuv in yuvs {
for ref frame in encoder
.encode(start.elapsed().as_millis() as _, yuv, STRIDE_ALIGN)
.unwrap()
{
size += frame.data.len();
av1s.push(frame.data.to_vec());
}
}
assert_eq!(av1s.len(), yuv_count);
println!(
"AV1 encode: {:?}, {} byte",
start.elapsed() / yuv_count as _,
size / yuv_count
);
let mut decoder = AomDecoder::new(AomDecoderConfig {
num_threads: (num_cpus::get() / 2) as _,
})
.unwrap();
let start = Instant::now();
for av1 in av1s {
let _ = decoder.decode(&av1);
let _ = decoder.flush();
}
println!("AV1 decode: {:?}", start.elapsed() / yuv_count as _);
}
#[cfg(feature = "hwcodec")]
mod hw {
use super::*;
@ -221,14 +255,19 @@ mod hw {
ctx.name = info.name;
let mut encoder = Encoder::new(ctx.clone()).unwrap();
let start = Instant::now();
let mut size = 0;
for yuv in yuvs {
let _ = encoder.encode(yuv).unwrap();
let frames = encoder.encode(yuv).unwrap();
for frame in frames {
size += frame.data.len();
}
}
println!(
"{}{}: {:?}",
"{}{}: {:?}, {} byte",
if best { "*" } else { "" },
ctx.name,
start.elapsed() / yuvs.len() as _
start.elapsed() / yuvs.len() as _,
size / yuvs.len(),
);
}

View File

@ -0,0 +1,10 @@
#include <aom/aom.h>
#include <aom/aom_image.h>
#include <aom/aom_integer.h>
#include <aom/aom_codec.h>
#include <aom/aom_external_partition.h>
#include <aom/aom_frame_buffer.h>
#include <aom/aom_encoder.h>
#include <aom/aom_decoder.h>
#include <aom/aomcx.h>
#include <aom/aomdx.h>

View File

@ -1,9 +1,9 @@
#include <vpx/vp8.h>
#include <vpx/vp8cx.h>
#include <vpx/vp8dx.h>
#include <vpx/vpx_codec.h>
#include <vpx/vpx_decoder.h>
#include <vpx/vpx_encoder.h>
#include <vpx/vpx_frame_buffer.h>
#include <vpx/vpx_image.h>
#include <vpx/vp8.h>
#include <vpx/vp8cx.h>
#include <vpx/vp8dx.h>
#include <vpx/vpx_codec.h>
#include <vpx/vpx_decoder.h>
#include <vpx/vpx_encoder.h>
#include <vpx/vpx_frame_buffer.h>
#include <vpx/vpx_image.h>
#include <vpx/vpx_integer.h>

View File

@ -50,8 +50,6 @@ impl crate::TraitCapturer for Capturer {
pub enum Frame<'a> {
RAW(&'a [u8]),
VP8(&'a [u8]),
VP9(&'a [u8]),
Empty,
}

View File

@ -0,0 +1,505 @@
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(improper_ctypes)]
#![allow(dead_code)]
include!(concat!(env!("OUT_DIR"), "/aom_ffi.rs"));
use crate::{codec::EncoderApi, EncodeFrame, STRIDE_ALIGN};
use crate::{common::GoogleImage, generate_call_macro, generate_call_ptr_macro, Error, Result};
use hbb_common::{
anyhow::{anyhow, Context},
bytes::Bytes,
log,
message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame},
ResultType,
};
use std::{ptr, slice};
generate_call_macro!(call_aom, false);
generate_call_macro!(call_aom_allow_err, true);
generate_call_ptr_macro!(call_aom_ptr);
impl Default for aom_codec_enc_cfg_t {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl Default for aom_codec_ctx_t {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl Default for aom_image_t {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
#[derive(Clone, Copy, Debug)]
pub struct AomEncoderConfig {
pub width: u32,
pub height: u32,
pub bitrate: u32,
}
pub struct AomEncoder {
ctx: aom_codec_ctx_t,
width: usize,
height: usize,
}
// https://webrtc.googlesource.com/src/+/refs/heads/main/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
mod webrtc {
use super::*;
const kQpMin: u32 = 10;
const kUsageProfile: u32 = AOM_USAGE_REALTIME;
const kMinQindex: u32 = 145; // Min qindex threshold for QP scaling.
const kMaxQindex: u32 = 205; // Max qindex threshold for QP scaling.
const kBitDepth: u32 = 8;
const kLagInFrames: u32 = 0; // No look ahead.
const kRtpTicksPerSecond: i32 = 90000;
const kMinimumFrameRate: f64 = 1.0;
const kQpMax: u32 = 25; // to-do: webrtc use dynamic value, no more than 63
fn number_of_threads(width: u32, height: u32, number_of_cores: usize) -> u32 {
// Keep the number of encoder threads equal to the possible number of
// column/row tiles, which is (1, 2, 4, 8). See comments below for
// AV1E_SET_TILE_COLUMNS/ROWS.
if width * height >= 640 * 360 && number_of_cores > 4 {
return 4;
} else if width * height >= 320 * 180 && number_of_cores > 2 {
return 2;
} else {
// Use 2 threads for low res on ARM.
#[cfg(any(target_arch = "arm", target_arch = "aarch64", target_os = "android"))]
if (width * height >= 320 * 180 && number_of_cores > 2) {
return 2;
}
// 1 thread less than VGA.
return 1;
}
}
// Only positive speeds, range for real-time coding currently is: 6 - 8.
// Lower means slower/better quality, higher means fastest/lower quality.
fn get_cpu_speed(width: u32, height: u32) -> u32 {
// aux_config_ = nullptr, kComplexityHigh
if width * height <= 320 * 180 {
8
} else if width * height <= 640 * 360 {
9
} else {
10
}
}
fn get_super_block_size(width: u32, height: u32, threads: u32) -> aom_superblock_size_t {
use aom_superblock_size::*;
let resolution = width * height;
if threads >= 4 && resolution >= 960 * 540 && resolution < 1920 * 1080 {
AOM_SUPERBLOCK_SIZE_64X64
} else {
AOM_SUPERBLOCK_SIZE_DYNAMIC
}
}
pub fn enc_cfg(
i: *const aom_codec_iface,
cfg: AomEncoderConfig,
) -> ResultType<aom_codec_enc_cfg> {
let mut c = unsafe { std::mem::MaybeUninit::zeroed().assume_init() };
call_aom!(aom_codec_enc_config_default(i, &mut c, kUsageProfile));
// Overwrite default config with input encoder settings & RTC-relevant values.
c.g_w = cfg.width;
c.g_h = cfg.height;
c.g_threads = number_of_threads(cfg.width, cfg.height, num_cpus::get());
c.g_timebase.num = 1;
c.g_timebase.den = kRtpTicksPerSecond;
c.rc_target_bitrate = cfg.bitrate; // kilobits/sec.
c.g_input_bit_depth = kBitDepth;
c.kf_mode = aom_kf_mode::AOM_KF_DISABLED;
c.rc_min_quantizer = kQpMin;
c.rc_max_quantizer = kQpMax;
c.rc_undershoot_pct = 50;
c.rc_overshoot_pct = 50;
c.rc_buf_initial_sz = 600;
c.rc_buf_optimal_sz = 600;
c.rc_buf_sz = 1000;
c.g_usage = kUsageProfile;
c.g_error_resilient = 0;
// Low-latency settings.
c.rc_end_usage = aom_rc_mode::AOM_CBR; // Constant Bit Rate (CBR) mode
c.g_pass = aom_enc_pass::AOM_RC_ONE_PASS; // One-pass rate control
c.g_lag_in_frames = kLagInFrames; // No look ahead when lag equals 0.
Ok(c)
}
pub fn set_controls(ctx: *mut aom_codec_ctx_t, cfg: &aom_codec_enc_cfg) -> ResultType<()> {
use aom_tune_content::*;
use aome_enc_control_id::*;
macro_rules! call_ctl {
($ctx:expr, $av1e:expr, $arg:expr) => {{
call_aom_allow_err!(aom_codec_control($ctx, $av1e as i32, $arg));
}};
}
call_ctl!(ctx, AOME_SET_CPUUSED, get_cpu_speed(cfg.g_w, cfg.g_h));
call_ctl!(ctx, AV1E_SET_ENABLE_CDEF, 1);
call_ctl!(ctx, AV1E_SET_ENABLE_TPL_MODEL, 0);
call_ctl!(ctx, AV1E_SET_DELTAQ_MODE, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_ORDER_HINT, 0);
call_ctl!(ctx, AV1E_SET_AQ_MODE, 3);
call_ctl!(ctx, AOME_SET_MAX_INTRA_BITRATE_PCT, 300);
call_ctl!(ctx, AV1E_SET_COEFF_COST_UPD_FREQ, 3);
call_ctl!(ctx, AV1E_SET_MODE_COST_UPD_FREQ, 3);
call_ctl!(ctx, AV1E_SET_MV_COST_UPD_FREQ, 3);
// kScreensharing
call_ctl!(ctx, AV1E_SET_TUNE_CONTENT, AOM_CONTENT_SCREEN);
call_ctl!(ctx, AV1E_SET_ENABLE_PALETTE, 1);
let tile_set = if cfg.g_threads == 4 && cfg.g_w == 640 && (cfg.g_h == 360 || cfg.g_h == 480)
{
AV1E_SET_TILE_ROWS
} else {
AV1E_SET_TILE_COLUMNS
};
// Failed on android
call_ctl!(ctx, tile_set, (cfg.g_threads as f64 * 1.0f64).log2().ceil());
call_ctl!(ctx, AV1E_SET_ROW_MT, 1);
call_ctl!(ctx, AV1E_SET_ENABLE_OBMC, 0);
call_ctl!(ctx, AV1E_SET_NOISE_SENSITIVITY, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_WARPED_MOTION, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_GLOBAL_MOTION, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_REF_FRAME_MVS, 0);
call_ctl!(
ctx,
AV1E_SET_SUPERBLOCK_SIZE,
get_super_block_size(cfg.g_w, cfg.g_h, cfg.g_threads)
);
call_ctl!(ctx, AV1E_SET_ENABLE_CFL_INTRA, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_SMOOTH_INTRA, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_ANGLE_DELTA, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_FILTER_INTRA, 0);
call_ctl!(ctx, AV1E_SET_INTRA_DEFAULT_TX_ONLY, 1);
call_ctl!(ctx, AV1E_SET_DISABLE_TRELLIS_QUANT, 1);
call_ctl!(ctx, AV1E_SET_ENABLE_DIST_WTD_COMP, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_DIFF_WTD_COMP, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_DUAL_FILTER, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_INTERINTRA_COMP, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_INTERINTRA_WEDGE, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_INTRA_EDGE_FILTER, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_INTRABC, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_MASKED_COMP, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_PAETH_INTRA, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_QM, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_RECT_PARTITIONS, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_RESTORATION, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_SMOOTH_INTERINTRA, 0);
call_ctl!(ctx, AV1E_SET_ENABLE_TX64, 0);
call_ctl!(ctx, AV1E_SET_MAX_REFERENCE_FRAMES, 3);
Ok(())
}
}
impl EncoderApi for AomEncoder {
fn new(cfg: crate::codec::EncoderCfg) -> ResultType<Self>
where
Self: Sized,
{
match cfg {
crate::codec::EncoderCfg::AOM(config) => {
let i = call_aom_ptr!(aom_codec_av1_cx());
let c = webrtc::enc_cfg(i, config)?;
let mut ctx = Default::default();
// Flag options: AOM_CODEC_USE_PSNR and AOM_CODEC_USE_HIGHBITDEPTH
let flags: aom_codec_flags_t = 0;
call_aom!(aom_codec_enc_init_ver(
&mut ctx,
i,
&c,
flags,
AOM_ENCODER_ABI_VERSION as _
));
webrtc::set_controls(&mut ctx, &c)?;
Ok(Self {
ctx,
width: config.width as _,
height: config.height as _,
})
}
_ => Err(anyhow!("encoder type mismatch")),
}
}
fn encode_to_message(&mut self, frame: &[u8], ms: i64) -> ResultType<Message> {
let mut frames = Vec::new();
for ref frame in self
.encode(ms, frame, STRIDE_ALIGN)
.with_context(|| "Failed to encode")?
{
frames.push(Self::create_frame(frame));
}
if frames.len() > 0 {
Ok(Self::create_msg(frames))
} else {
Err(anyhow!("no valid frame"))
}
}
fn use_yuv(&self) -> bool {
true
}
fn set_bitrate(&mut self, bitrate: u32) -> ResultType<()> {
let mut new_enc_cfg = unsafe { *self.ctx.config.enc.to_owned() };
new_enc_cfg.rc_target_bitrate = bitrate;
call_aom!(aom_codec_enc_config_set(&mut self.ctx, &new_enc_cfg));
return Ok(());
}
}
impl AomEncoder {
pub fn encode(&mut self, pts: i64, data: &[u8], stride_align: usize) -> Result<EncodeFrames> {
if 2 * data.len() < 3 * self.width * self.height {
return Err(Error::FailedCall("len not enough".to_string()));
}
let mut image = Default::default();
call_aom_ptr!(aom_img_wrap(
&mut image,
aom_img_fmt::AOM_IMG_FMT_I420,
self.width as _,
self.height as _,
stride_align as _,
data.as_ptr() as _,
));
call_aom!(aom_codec_encode(
&mut self.ctx,
&image,
pts as _,
1, // Duration
0, // Flags
));
Ok(EncodeFrames {
ctx: &mut self.ctx,
iter: ptr::null(),
})
}
#[inline]
pub fn create_msg(frames: Vec<EncodedVideoFrame>) -> Message {
let mut msg_out = Message::new();
let mut vf = VideoFrame::new();
let av1s = EncodedVideoFrames {
frames: frames.into(),
..Default::default()
};
vf.set_av1s(av1s);
msg_out.set_video_frame(vf);
msg_out
}
#[inline]
fn create_frame(frame: &EncodeFrame) -> EncodedVideoFrame {
EncodedVideoFrame {
data: Bytes::from(frame.data.to_vec()),
key: frame.key,
pts: frame.pts,
..Default::default()
}
}
}
impl Drop for AomEncoder {
fn drop(&mut self) {
unsafe {
let result = aom_codec_destroy(&mut self.ctx);
if result != aom_codec_err_t::AOM_CODEC_OK {
panic!("failed to destroy aom codec");
}
}
}
}
pub struct EncodeFrames<'a> {
ctx: &'a mut aom_codec_ctx_t,
iter: aom_codec_iter_t,
}
impl<'a> Iterator for EncodeFrames<'a> {
type Item = EncodeFrame<'a>;
fn next(&mut self) -> Option<Self::Item> {
loop {
unsafe {
let pkt = aom_codec_get_cx_data(self.ctx, &mut self.iter);
if pkt.is_null() {
return None;
} else if (*pkt).kind == aom_codec_cx_pkt_kind::AOM_CODEC_CX_FRAME_PKT {
let f = &(*pkt).data.frame;
return Some(Self::Item {
data: slice::from_raw_parts(f.buf as _, f.sz as _),
key: (f.flags & AOM_FRAME_IS_KEY) != 0,
pts: f.pts,
});
} else {
// Ignore the packet.
}
}
}
}
}
pub struct AomDecoderConfig {
pub num_threads: u32,
}
pub struct AomDecoder {
ctx: aom_codec_ctx_t,
}
impl AomDecoder {
pub fn new(cfg: AomDecoderConfig) -> Result<Self> {
let i = call_aom_ptr!(aom_codec_av1_dx());
let mut ctx = Default::default();
let cfg = aom_codec_dec_cfg_t {
threads: if cfg.num_threads == 0 {
num_cpus::get() as _
} else {
cfg.num_threads
},
w: 0,
h: 0,
allow_lowbitdepth: 1,
};
call_aom!(aom_codec_dec_init_ver(
&mut ctx,
i,
&cfg,
0,
AOM_DECODER_ABI_VERSION as _,
));
Ok(Self { ctx })
}
pub fn decode(&mut self, data: &[u8]) -> Result<DecodeFrames> {
call_aom!(aom_codec_decode(
&mut self.ctx,
data.as_ptr(),
data.len() as _,
ptr::null_mut(),
));
Ok(DecodeFrames {
ctx: &mut self.ctx,
iter: ptr::null(),
})
}
/// Notify the decoder to return any pending frame
pub fn flush(&mut self) -> Result<DecodeFrames> {
call_aom!(aom_codec_decode(
&mut self.ctx,
ptr::null(),
0,
ptr::null_mut(),
));
Ok(DecodeFrames {
ctx: &mut self.ctx,
iter: ptr::null(),
})
}
}
impl Drop for AomDecoder {
fn drop(&mut self) {
unsafe {
let result = aom_codec_destroy(&mut self.ctx);
if result != aom_codec_err_t::AOM_CODEC_OK {
panic!("failed to destroy aom codec");
}
}
}
}
pub struct DecodeFrames<'a> {
ctx: &'a mut aom_codec_ctx_t,
iter: aom_codec_iter_t,
}
impl<'a> Iterator for DecodeFrames<'a> {
type Item = Image;
fn next(&mut self) -> Option<Self::Item> {
let img = unsafe { aom_codec_get_frame(self.ctx, &mut self.iter) };
if img.is_null() {
return None;
} else {
return Some(Image(img));
}
}
}
pub struct Image(*mut aom_image_t);
impl Image {
#[inline]
pub fn new() -> Self {
Self(std::ptr::null_mut())
}
#[inline]
pub fn is_null(&self) -> bool {
self.0.is_null()
}
#[inline]
pub fn format(&self) -> aom_img_fmt_t {
self.inner().fmt
}
#[inline]
pub fn inner(&self) -> &aom_image_t {
unsafe { &*self.0 }
}
}
impl GoogleImage for Image {
#[inline]
fn width(&self) -> usize {
self.inner().d_w as _
}
#[inline]
fn height(&self) -> usize {
self.inner().d_h as _
}
#[inline]
fn stride(&self) -> Vec<i32> {
self.inner().stride.iter().map(|x| *x as i32).collect()
}
#[inline]
fn planes(&self) -> Vec<*mut u8> {
self.inner().planes.iter().map(|p| *p as *mut u8).collect()
}
}
impl Drop for Image {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { aom_img_free(self.0) };
}
}
}
unsafe impl Send for aom_codec_ctx_t {}

View File

@ -10,7 +10,12 @@ use crate::hwcodec::*;
use crate::mediacodec::{
MediaCodecDecoder, MediaCodecDecoders, H264_DECODER_SUPPORT, H265_DECODER_SUPPORT,
};
use crate::{vpxcodec::*, CodecName, ImageRgb};
use crate::{
aom::{self, AomDecoder, AomDecoderConfig, AomEncoder, AomEncoderConfig},
common::GoogleImage,
vpxcodec::{self, VpxDecoder, VpxDecoderConfig, VpxEncoder, VpxEncoderConfig, VpxVideoCodecId},
CodecName, ImageRgb,
};
#[cfg(not(any(target_os = "android", target_os = "ios")))]
use hbb_common::sysinfo::{System, SystemExt};
@ -43,6 +48,7 @@ pub struct HwEncoderConfig {
#[derive(Debug, Clone)]
pub enum EncoderCfg {
VPX(VpxEncoderConfig),
AOM(AomEncoderConfig),
HW(HwEncoderConfig),
}
@ -79,6 +85,7 @@ impl DerefMut for Encoder {
pub struct Decoder {
vp8: VpxDecoder,
vp9: VpxDecoder,
av1: AomDecoder,
#[cfg(feature = "hwcodec")]
hw: HwDecoders,
#[cfg(feature = "hwcodec")]
@ -101,6 +108,9 @@ impl Encoder {
EncoderCfg::VPX(_) => Ok(Encoder {
codec: Box::new(VpxEncoder::new(config)?),
}),
EncoderCfg::AOM(_) => Ok(Encoder {
codec: Box::new(AomEncoder::new(config)?),
}),
#[cfg(feature = "hwcodec")]
EncoderCfg::HW(_) => match HwEncoder::new(config) {
@ -139,6 +149,7 @@ impl Encoder {
}
let vp8_useable = decodings.len() > 0 && decodings.iter().all(|(_, s)| s.ability_vp8 > 0);
let av1_useable = decodings.len() > 0 && decodings.iter().all(|(_, s)| s.ability_av1 > 0);
#[allow(unused_mut)]
let mut h264_name = None;
#[allow(unused_mut)]
@ -167,6 +178,7 @@ impl Encoder {
.filter(|(_, s)| {
s.prefer == PreferCodec::VP9.into()
|| s.prefer == PreferCodec::VP8.into() && vp8_useable
|| s.prefer == PreferCodec::AV1.into() && av1_useable
|| s.prefer == PreferCodec::H264.into() && h264_name.is_some()
|| s.prefer == PreferCodec::H265.into() && h265_name.is_some()
})
@ -187,6 +199,7 @@ impl Encoder {
match preference {
PreferCodec::VP8 => *name = CodecName::VP8,
PreferCodec::VP9 => *name = CodecName::VP9,
PreferCodec::AV1 => *name = CodecName::AV1,
PreferCodec::H264 => *name = h264_name.map_or(auto_codec, |c| CodecName::H264(c)),
PreferCodec::H265 => *name = h265_name.map_or(auto_codec, |c| CodecName::H265(c)),
PreferCodec::Auto => *name = auto_codec,
@ -209,6 +222,7 @@ impl Encoder {
#[allow(unused_mut)]
let mut encoding = SupportedEncoding {
vp8: true,
av1: true,
..Default::default()
};
#[cfg(feature = "hwcodec")]
@ -227,6 +241,7 @@ impl Decoder {
let mut decoding = SupportedDecoding {
ability_vp8: 1,
ability_vp9: 1,
ability_av1: 1,
prefer: id_for_perfer
.map_or(PreferCodec::Auto, |id| Self::codec_preference(id))
.into(),
@ -267,9 +282,14 @@ impl Decoder {
num_threads: (num_cpus::get() / 2) as _,
})
.unwrap();
let av1 = AomDecoder::new(AomDecoderConfig {
num_threads: (num_cpus::get() / 2) as _,
})
.unwrap();
Decoder {
vp8,
vp9,
av1,
#[cfg(feature = "hwcodec")]
hw: if enable_hwcodec_option() {
HwDecoder::new_decoders()
@ -300,6 +320,9 @@ impl Decoder {
video_frame::Union::Vp9s(vp9s) => {
Decoder::handle_vpxs_video_frame(&mut self.vp9, vp9s, rgb)
}
video_frame::Union::Av1s(av1s) => {
Decoder::handle_av1s_video_frame(&mut self.av1, av1s, rgb)
}
#[cfg(feature = "hwcodec")]
video_frame::Union::H264s(h264s) => {
if let Some(decoder) = &mut self.hw.h264 {
@ -342,7 +365,7 @@ impl Decoder {
vpxs: &EncodedVideoFrames,
rgb: &mut ImageRgb,
) -> ResultType<bool> {
let mut last_frame = Image::new();
let mut last_frame = vpxcodec::Image::new();
for vpx in vpxs.frames.iter() {
for frame in decoder.decode(&vpx.data)? {
drop(last_frame);
@ -361,6 +384,31 @@ impl Decoder {
}
}
// rgb [in/out] fmt and stride must be set in ImageRgb
fn handle_av1s_video_frame(
decoder: &mut AomDecoder,
av1s: &EncodedVideoFrames,
rgb: &mut ImageRgb,
) -> ResultType<bool> {
let mut last_frame = aom::Image::new();
for av1 in av1s.frames.iter() {
for frame in decoder.decode(&av1.data)? {
drop(last_frame);
last_frame = frame;
}
}
for frame in decoder.flush()? {
drop(last_frame);
last_frame = frame;
}
if last_frame.is_null() {
Ok(false)
} else {
last_frame.to(rgb);
Ok(true)
}
}
// rgb [in/out] fmt and stride must be set in ImageRgb
#[cfg(feature = "hwcodec")]
fn handle_hw_video_frame(
@ -404,6 +452,8 @@ impl Decoder {
PreferCodec::VP8
} else if codec == "vp9" {
PreferCodec::VP9
} else if codec == "av1" {
PreferCodec::AV1
} else if codec == "h264" {
PreferCodec::H264
} else if codec == "h265" {

View File

@ -1,5 +1,6 @@
pub use self::vpxcodec::*;
use hbb_common::message_proto::{video_frame, VideoFrame};
use std::slice;
cfg_if! {
if #[cfg(quartz)] {
@ -41,6 +42,7 @@ pub use self::convert::*;
pub const STRIDE_ALIGN: usize = 64; // commonly used in libvpx vpx_img_alloc caller
pub const HW_STRIDE_ALIGN: usize = 0; // recommended by av_frame_get_buffer
pub mod aom;
pub mod record;
mod vpx;
@ -132,6 +134,7 @@ pub fn is_cursor_embedded() -> bool {
pub enum CodecName {
VP8,
VP9,
AV1,
H264(String),
H265(String),
}
@ -140,6 +143,7 @@ pub enum CodecName {
pub enum CodecFormat {
VP8,
VP9,
AV1,
H264,
H265,
Unknown,
@ -150,6 +154,7 @@ impl From<&VideoFrame> for CodecFormat {
match it.union {
Some(video_frame::Union::Vp8s(_)) => CodecFormat::VP8,
Some(video_frame::Union::Vp9s(_)) => CodecFormat::VP9,
Some(video_frame::Union::Av1s(_)) => CodecFormat::AV1,
Some(video_frame::Union::H264s(_)) => CodecFormat::H264,
Some(video_frame::Union::H265s(_)) => CodecFormat::H265,
_ => CodecFormat::Unknown,
@ -162,6 +167,7 @@ impl From<&CodecName> for CodecFormat {
match value {
CodecName::VP8 => Self::VP8,
CodecName::VP9 => Self::VP9,
CodecName::AV1 => Self::AV1,
CodecName::H264(_) => Self::H264,
CodecName::H265(_) => Self::H265,
}
@ -173,9 +179,162 @@ impl ToString for CodecFormat {
match self {
CodecFormat::VP8 => "VP8".into(),
CodecFormat::VP9 => "VP9".into(),
CodecFormat::AV1 => "AV1".into(),
CodecFormat::H264 => "H264".into(),
CodecFormat::H265 => "H265".into(),
CodecFormat::Unknown => "Unknow".into(),
}
}
}
#[derive(Debug)]
pub enum Error {
FailedCall(String),
BadPtr(String),
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
write!(f, "{:?}", self)
}
}
impl std::error::Error for Error {}
pub type Result<T> = std::result::Result<T, Error>;
#[macro_export]
macro_rules! generate_call_macro {
($func_name:ident, $allow_err:expr) => {
macro_rules! $func_name {
($x:expr) => {{
let result = unsafe { $x };
let result_int = unsafe { std::mem::transmute::<_, i32>(result) };
if result_int != 0 {
let message = format!(
"errcode={} {}:{}:{}:{}",
result_int,
module_path!(),
file!(),
line!(),
column!()
);
if $allow_err {
log::warn!("Failed to call {}, {}", stringify!($func_name), message);
} else {
return Err(crate::Error::FailedCall(message).into());
}
}
result
}};
}
};
}
#[macro_export]
macro_rules! generate_call_ptr_macro {
($func_name:ident) => {
macro_rules! $func_name {
($x:expr) => {{
let result = unsafe { $x };
let result_int = unsafe { std::mem::transmute::<_, isize>(result) };
if result_int == 0 {
return Err(crate::Error::BadPtr(format!(
"errcode={} {}:{}:{}:{}",
result_int,
module_path!(),
file!(),
line!(),
column!()
))
.into());
}
result
}};
}
};
}
pub trait GoogleImage {
fn width(&self) -> usize;
fn height(&self) -> usize;
fn stride(&self) -> Vec<i32>;
fn planes(&self) -> Vec<*mut u8>;
fn get_bytes_per_row(w: usize, fmt: ImageFormat, stride: usize) -> usize {
let bytes_per_pixel = match fmt {
ImageFormat::Raw => 3,
ImageFormat::ARGB | ImageFormat::ABGR => 4,
};
// https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128
// https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129
(w * bytes_per_pixel + stride - 1) & !(stride - 1)
}
// rgb [in/out] fmt and stride must be set in ImageRgb
fn to(&self, rgb: &mut ImageRgb) {
rgb.w = self.width();
rgb.h = self.height();
let bytes_per_row = Self::get_bytes_per_row(rgb.w, rgb.fmt, rgb.stride());
rgb.raw.resize(rgb.h * bytes_per_row, 0);
let stride = self.stride();
let planes = self.planes();
unsafe {
match rgb.fmt() {
ImageFormat::Raw => {
super::I420ToRAW(
planes[0],
stride[0],
planes[1],
stride[1],
planes[2],
stride[2],
rgb.raw.as_mut_ptr(),
bytes_per_row as _,
self.width() as _,
self.height() as _,
);
}
ImageFormat::ARGB => {
super::I420ToARGB(
planes[0],
stride[0],
planes[1],
stride[1],
planes[2],
stride[2],
rgb.raw.as_mut_ptr(),
bytes_per_row as _,
self.width() as _,
self.height() as _,
);
}
ImageFormat::ABGR => {
super::I420ToABGR(
planes[0],
stride[0],
planes[1],
stride[1],
planes[2],
stride[2],
rgb.raw.as_mut_ptr(),
bytes_per_row as _,
self.width() as _,
self.height() as _,
);
}
}
}
}
fn data(&self) -> (&[u8], &[u8], &[u8]) {
unsafe {
let stride = self.stride();
let planes = self.planes();
let h = (self.height() as usize + 1) & !1;
let n = stride[0] as usize * h;
let y = slice::from_raw_parts(planes[0], n);
let n = stride[1] as usize * (h >> 1);
let u = slice::from_raw_parts(planes[1], n);
let v = slice::from_raw_parts(planes[2], n);
(y, u, v)
}
}
}

View File

@ -3,17 +3,22 @@
// https://github.com/rust-av/vpx-rs/blob/master/src/decoder.rs
use hbb_common::anyhow::{anyhow, Context};
use hbb_common::log;
use hbb_common::message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame};
use hbb_common::ResultType;
use crate::STRIDE_ALIGN;
use crate::{codec::EncoderApi, ImageFormat, ImageRgb};
use crate::codec::EncoderApi;
use crate::{GoogleImage, STRIDE_ALIGN};
use super::vpx::{vp8e_enc_control_id::*, vpx_codec_err_t::*, *};
use crate::{generate_call_macro, generate_call_ptr_macro, Error, Result};
use hbb_common::bytes::Bytes;
use std::os::raw::{c_int, c_uint};
use std::{ptr, slice};
generate_call_macro!(call_vpx, false);
generate_call_ptr_macro!(call_vpx_ptr);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum VpxVideoCodecId {
VP8,
@ -37,60 +42,6 @@ pub struct VpxDecoder {
ctx: vpx_codec_ctx_t,
}
#[derive(Debug)]
pub enum Error {
FailedCall(String),
BadPtr(String),
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
write!(f, "{:?}", self)
}
}
impl std::error::Error for Error {}
pub type Result<T> = std::result::Result<T, Error>;
macro_rules! call_vpx {
($x:expr) => {{
let result = unsafe { $x }; // original expression
let result_int = unsafe { std::mem::transmute::<_, i32>(result) };
if result_int != 0 {
return Err(Error::FailedCall(format!(
"errcode={} {}:{}:{}:{}",
result_int,
module_path!(),
file!(),
line!(),
column!()
))
.into());
}
result
}};
}
macro_rules! call_vpx_ptr {
($x:expr) => {{
let result = unsafe { $x }; // original expression
let result_int = unsafe { std::mem::transmute::<_, isize>(result) };
if result_int == 0 {
return Err(Error::BadPtr(format!(
"errcode={} {}:{}:{}:{}",
result_int,
module_path!(),
file!(),
line!(),
column!()
))
.into());
}
result
}};
}
impl EncoderApi for VpxEncoder {
fn new(cfg: crate::codec::EncoderCfg) -> ResultType<Self>
where
@ -495,16 +446,6 @@ impl Image {
self.0.is_null()
}
#[inline]
pub fn width(&self) -> usize {
self.inner().d_w as _
}
#[inline]
pub fn height(&self) -> usize {
self.inner().d_h as _
}
#[inline]
pub fn format(&self) -> vpx_img_fmt_t {
// VPX_IMG_FMT_I420
@ -515,90 +456,27 @@ impl Image {
pub fn inner(&self) -> &vpx_image_t {
unsafe { &*self.0 }
}
}
impl GoogleImage for Image {
#[inline]
pub fn stride(&self, iplane: usize) -> i32 {
self.inner().stride[iplane]
fn width(&self) -> usize {
self.inner().d_w as _
}
#[inline]
pub fn get_bytes_per_row(w: usize, fmt: ImageFormat, stride: usize) -> usize {
let bytes_per_pixel = match fmt {
ImageFormat::Raw => 3,
ImageFormat::ARGB | ImageFormat::ABGR => 4,
};
// https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128
// https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129
(w * bytes_per_pixel + stride - 1) & !(stride - 1)
}
// rgb [in/out] fmt and stride must be set in ImageRgb
pub fn to(&self, rgb: &mut ImageRgb) {
rgb.w = self.width();
rgb.h = self.height();
let bytes_per_row = Self::get_bytes_per_row(rgb.w, rgb.fmt, rgb.stride());
rgb.raw.resize(rgb.h * bytes_per_row, 0);
let img = self.inner();
unsafe {
match rgb.fmt() {
ImageFormat::Raw => {
super::I420ToRAW(
img.planes[0],
img.stride[0],
img.planes[1],
img.stride[1],
img.planes[2],
img.stride[2],
rgb.raw.as_mut_ptr(),
bytes_per_row as _,
self.width() as _,
self.height() as _,
);
}
ImageFormat::ARGB => {
super::I420ToARGB(
img.planes[0],
img.stride[0],
img.planes[1],
img.stride[1],
img.planes[2],
img.stride[2],
rgb.raw.as_mut_ptr(),
bytes_per_row as _,
self.width() as _,
self.height() as _,
);
}
ImageFormat::ABGR => {
super::I420ToABGR(
img.planes[0],
img.stride[0],
img.planes[1],
img.stride[1],
img.planes[2],
img.stride[2],
rgb.raw.as_mut_ptr(),
bytes_per_row as _,
self.width() as _,
self.height() as _,
);
}
}
}
fn height(&self) -> usize {
self.inner().d_h as _
}
#[inline]
pub fn data(&self) -> (&[u8], &[u8], &[u8]) {
unsafe {
let img = self.inner();
let h = (img.d_h as usize + 1) & !1;
let n = img.stride[0] as usize * h;
let y = slice::from_raw_parts(img.planes[0], n);
let n = img.stride[1] as usize * (h >> 1);
let u = slice::from_raw_parts(img.planes[1], n);
let v = slice::from_raw_parts(img.planes[2], n);
(y, u, v)
}
fn stride(&self) -> Vec<i32> {
self.inner().stride.iter().map(|x| *x as i32).collect()
}
#[inline]
fn planes(&self) -> Vec<*mut u8> {
self.inner().planes.iter().map(|p| *p as *mut u8).collect()
}
}

View File

@ -844,7 +844,7 @@ impl<T: InvokeUiSession> Remote<T> {
use video_frame::Union::*;
match &vf.union {
Some(vf) => match vf {
Vp8s(f) | Vp9s(f) | H264s(f) | H265s(f) => f.frames.iter().any(|e| e.key),
Vp8s(f) | Vp9s(f) | Av1s(f) | H264s(f) | H265s(f) => f.frames.iter().any(|e| e.key),
_ => false,
},
None => false,

View File

@ -1100,8 +1100,8 @@ pub fn session_send_note(id: String, note: String) {
pub fn session_alternative_codecs(id: String) -> String {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
let (vp8, h264, h265) = session.alternative_codecs();
let msg = HashMap::from([("vp8", vp8), ("h264", h264), ("h265", h265)]);
let (vp8, av1, h264, h265) = session.alternative_codecs();
let msg = HashMap::from([("vp8", vp8), ("av1", av1), ("h264", h264), ("h265", h265)]);
serde_json::ser::to_string(&msg).unwrap_or("".to_owned())
} else {
String::new()

View File

@ -35,6 +35,7 @@ use hbb_common::{
#[cfg(not(windows))]
use scrap::Capturer;
use scrap::{
aom::AomEncoderConfig,
codec::{Encoder, EncoderCfg, HwEncoderConfig},
record::{Recorder, RecorderContext},
vpxcodec::{VpxEncoderConfig, VpxVideoCodecId},
@ -549,6 +550,11 @@ fn run(sp: GenericService) -> ResultType<()> {
num_threads: (num_cpus::get() / 2) as _,
})
}
scrap::CodecName::AV1 => EncoderCfg::AOM(AomEncoderConfig {
width: c.width as _,
height: c.height as _,
bitrate: bitrate as _,
}),
};
let mut encoder;
@ -674,16 +680,6 @@ fn run(sp: GenericService) -> ResultType<()> {
let time = now - start;
let ms = (time.as_secs() * 1000 + time.subsec_millis() as u64) as i64;
match frame {
scrap::Frame::VP8(data) => {
let send_conn_ids =
handle_one_frame_encoded(VpxVideoCodecId::VP8, &sp, data, ms)?;
frame_controller.set_send(now, send_conn_ids);
}
scrap::Frame::VP9(data) => {
let send_conn_ids =
handle_one_frame_encoded(VpxVideoCodecId::VP9, &sp, data, ms)?;
frame_controller.set_send(now, send_conn_ids);
}
scrap::Frame::RAW(data) => {
if data.len() != 0 {
let send_conn_ids =
@ -870,31 +866,6 @@ fn handle_one_frame(
Ok(send_conn_ids)
}
#[inline]
#[cfg(any(target_os = "android", target_os = "ios"))]
pub fn handle_one_frame_encoded(
codec: VpxVideoCodecId,
sp: &GenericService,
frame: &[u8],
ms: i64,
) -> ResultType<HashSet<i32>> {
sp.snapshot(|sps| {
// so that new sub and old sub share the same encoder after switch
if sps.has_subscribes() {
bail!("SWITCH");
}
Ok(())
})?;
let vpx_frame = EncodedVideoFrame {
data: frame.to_vec().into(),
key: true,
pts: ms,
..Default::default()
};
let send_conn_ids = sp.send_video_frame(scrap::VpxEncoder::create_msg(codec, vec![vpx_frame]));
Ok(send_conn_ids)
}
#[inline]
fn get_original_resolution(display_name: &str, w: usize, h: usize) -> MessageField<Resolution> {
#[cfg(all(windows, feature = "virtual_display_driver"))]

View File

@ -162,7 +162,7 @@ class Header: Reactor.Component {
function renderDisplayPop() {
var codecs = handler.alternative_codecs();
var show_codec = codecs[0] || codecs[1] || codecs[2];
var show_codec = codecs[0] || codecs[1] || codecs[2] || codecs[3];
var cursor_embedded = false;
if ((pi.displays || []).length > 0) {
@ -188,8 +188,9 @@ class Header: Reactor.Component {
<li #auto type="codec-preference"><span>{svg_checkmark}</span>Auto</li>
{codecs[0] ? <li #vp8 type="codec-preference"><span>{svg_checkmark}</span>VP8</li> : ""}
<li #vp9 type="codec-preference"><span>{svg_checkmark}</span>VP9</li>
{codecs[1] ? <li #h264 type="codec-preference"><span>{svg_checkmark}</span>H264</li> : ""}
{codecs[2] ? <li #h265 type="codec-preference"><span>{svg_checkmark}</span>H265</li> : ""}
{codecs[1] ? <li #av1 type="codec-preference"><span>{svg_checkmark}</span>AV1</li> : ""}
{codecs[2] ? <li #h264 type="codec-preference"><span>{svg_checkmark}</span>H264</li> : ""}
{codecs[3] ? <li #h265 type="codec-preference"><span>{svg_checkmark}</span>H265</li> : ""}
</div> : ""}
<div .separator />
{!cursor_embedded && <li #show-remote-cursor .toggle-option><span>{svg_checkmark}</span>{translate('Show remote cursor')}</li>}

View File

@ -520,9 +520,10 @@ impl SciterSession {
}
fn alternative_codecs(&self) -> Value {
let (vp8, h264, h265) = self.0.alternative_codecs();
let (vp8, av1, h264, h265) = self.0.alternative_codecs();
let mut v = Value::array(0);
v.push(vp8);
v.push(av1);
v.push(h264);
v.push(h265);
v

View File

@ -225,16 +225,18 @@ impl<T: InvokeUiSession> Session<T> {
true
}
pub fn alternative_codecs(&self) -> (bool, bool, bool) {
pub fn alternative_codecs(&self) -> (bool, bool, bool, bool) {
let decoder = scrap::codec::Decoder::supported_decodings(None);
let mut vp8 = decoder.ability_vp8 > 0;
let mut av1 = decoder.ability_av1 > 0;
let mut h264 = decoder.ability_h264 > 0;
let mut h265 = decoder.ability_h265 > 0;
let enc = &self.lc.read().unwrap().supported_encoding;
vp8 = vp8 && enc.vp8;
av1 = av1 && enc.av1;
h264 = h264 && enc.h264;
h265 = h265 && enc.h265;
(vp8, h264, h265)
(vp8, av1, h264, h265)
}
pub fn change_prefer_codec(&self) {