mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 23:37:33 +09:00
Vendor dav1d 1.5.3
This commit is contained in:
parent
a852c0a86a
commit
ee30135ecc
390 changed files with 325535 additions and 0 deletions
10
media/libdav1d/src/.gitignore
vendored
Normal file
10
media/libdav1d/src/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/build*
|
||||
/Session.vim
|
||||
[._]*.swp
|
||||
*~
|
||||
tags
|
||||
.DS_Store
|
||||
/tests/argon
|
||||
/tests/dav1d-test-data
|
||||
*.snap
|
||||
/tools/output/xxhash.h
|
||||
930
media/libdav1d/src/.gitlab-ci.yml
Normal file
930
media/libdav1d/src/.gitlab-ci.yml
Normal file
|
|
@ -0,0 +1,930 @@
|
|||
stages:
|
||||
- style
|
||||
- build
|
||||
- test
|
||||
|
||||
.debian-amd64-common:
|
||||
image: registry.videolan.org/dav1d-debian-unstable:20250207200301
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
- amd64
|
||||
|
||||
.debian-amd64-minimum:
|
||||
image: registry.videolan.org/dav1d-debian-minimum:20250207200301
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
- amd64
|
||||
|
||||
.debian-llvm-mingw-common:
|
||||
image: registry.videolan.org/vlc-debian-llvm-msvcrt:20250305204125
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
- amd64
|
||||
|
||||
.debian-aarch64-common:
|
||||
image: registry.videolan.org/dav1d-debian-bookworm-aarch64:20250215002814
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
- aarch64
|
||||
|
||||
.debian-armv7-common:
|
||||
image: registry.videolan.org/dav1d-debian-bookworm-armv7:20250215014239
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
- armv7
|
||||
|
||||
.debian-ppc64le-common:
|
||||
image: registry.videolan.org/dav1d-debian-unstable-ppc64le:20250215003029
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
- ppc64le
|
||||
|
||||
.android-common:
|
||||
image: registry.videolan.org/vlc-debian-android:20241118101328
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
- amd64
|
||||
|
||||
.debian-wasm-emscripten-common:
|
||||
image: registry.videolan.org/vlc-debian-wasm-emscripten:20250207201514
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
- amd64
|
||||
|
||||
|
||||
style-check:
|
||||
extends: .debian-amd64-common
|
||||
stage: style
|
||||
script:
|
||||
- git grep -I -n -P "\t|\r| $" -- . ':(exclude)*/compat/*' && echo "Trailing whitespace" && exit 1
|
||||
- git grep -I -n -i -e 'david' --and --not -e 'copyright' -- . ':(exclude)THANKS.md' ':(exclude).gitlab-ci.yml' && echo "Misspelled dav1d" && exit 1
|
||||
- git grep -I -l -z "" -- . ':(exclude)*/compat/*' | while IFS= read -r -d '' i; do
|
||||
if [ -n "$(tail -c 1 "$i")" ]; then
|
||||
echo "No newline at end of $i";
|
||||
exit 1;
|
||||
fi;
|
||||
done
|
||||
- rg '[\u061c\u2000-\u200f\u2028-\u202f\u205f-\u206f]' ./ && echo "Invisible Unicode characters" && exit 1
|
||||
- git remote rm upstream 2> /dev/null || true
|
||||
- git remote add upstream https://code.videolan.org/videolan/dav1d.git
|
||||
- git fetch -q upstream master
|
||||
- for i in $(git rev-list HEAD ^upstream/master); do
|
||||
echo "Checking commit message of $i";
|
||||
msg="$(git log --format=%B -n 1 $i)";
|
||||
if [ -n "$(echo "$msg" | awk "NR==2")" ]; then
|
||||
echo "Malformed commit message in $i, second line must be empty";
|
||||
exit 1;
|
||||
fi;
|
||||
if echo "$msg" | head -1 | grep -q '\.$'; then
|
||||
echo "Malformed commit message in $i, trailing period in subject line";
|
||||
exit 1;
|
||||
fi;
|
||||
done
|
||||
|
||||
x86inc-check:
|
||||
extends: .debian-amd64-common
|
||||
stage: style
|
||||
script:
|
||||
- git remote rm x86inc 2> /dev/null || true
|
||||
- git remote add x86inc https://code.videolan.org/videolan/x86inc.asm.git
|
||||
- git fetch -q x86inc master
|
||||
- git diff --exit-code x86inc/master:x86inc.asm src/ext/x86/x86inc.asm
|
||||
allow_failure: true
|
||||
|
||||
|
||||
build-debian:
|
||||
extends: .debian-amd64-common
|
||||
tags:
|
||||
- docker
|
||||
- avx2
|
||||
- amd64
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtrim_dsp=false
|
||||
--werror
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
artifacts:
|
||||
paths:
|
||||
- build/
|
||||
expire_in: 1 day
|
||||
|
||||
build-debian-static:
|
||||
extends: .debian-amd64-common
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--default-library static
|
||||
--werror
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
- nm -A -g src/libdav1d.a | grep " [ABCDGRST] " | (! grep -v " _*dav1d_")
|
||||
|
||||
build-debian-illegal-instructions:
|
||||
extends: .debian-amd64-common
|
||||
tags:
|
||||
- docker
|
||||
- avx2
|
||||
- amd64
|
||||
script:
|
||||
- meson setup build --buildtype debug
|
||||
- ninja -C build
|
||||
- cd build
|
||||
- exit_code=0
|
||||
- time meson test -v --suite checkasm --wrapper 'qemu-x86_64 -cpu Conroe' || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --suite checkasm --wrapper 'qemu-x86_64 -cpu Penryn' || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
build-debian32:
|
||||
extends: .debian-amd64-common
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtrim_dsp=false
|
||||
--werror
|
||||
--cross-file package/crossfiles/i686-linux32.meson
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
artifacts:
|
||||
paths:
|
||||
- build/
|
||||
expire_in: 1 day
|
||||
|
||||
build-debian-examples:
|
||||
extends: .debian-amd64-common
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
-Denable_examples=true
|
||||
- ninja -C build
|
||||
|
||||
build-debian-no-tools:
|
||||
extends: .debian-amd64-common
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
-Denable_tools=false
|
||||
- ninja -C build
|
||||
|
||||
build-debian-bitdepth:
|
||||
extends: .debian-amd64-common
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
-Dbitdepths=$DEPTH
|
||||
- ninja -C build
|
||||
parallel:
|
||||
matrix:
|
||||
- DEPTH: [8, 16]
|
||||
|
||||
build-debian-avx:
|
||||
extends: .debian-amd64-common
|
||||
tags:
|
||||
- docker
|
||||
- avx2
|
||||
- amd64
|
||||
variables:
|
||||
CFLAGS: '-mavx'
|
||||
script:
|
||||
- meson setup build --buildtype debugoptimized
|
||||
--werror
|
||||
- ninja -C build
|
||||
- cd build
|
||||
- time meson test -v --suite checkasm
|
||||
|
||||
build-debian-minimum:
|
||||
extends: .debian-amd64-minimum
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-debian-avx512:
|
||||
extends: .debian-amd64-common
|
||||
tags:
|
||||
- docker
|
||||
- amd64-avx512
|
||||
variables:
|
||||
CFLAGS: '-mavx'
|
||||
script:
|
||||
- meson setup build --buildtype debugoptimized
|
||||
--werror
|
||||
- ninja -C build
|
||||
- cd build
|
||||
- time meson test -v --suite checkasm
|
||||
|
||||
build-debian-clang:
|
||||
extends: .debian-amd64-common
|
||||
variables:
|
||||
CC: clang
|
||||
CC_LD: mold
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-win:
|
||||
extends: .debian-amd64-common
|
||||
script:
|
||||
- wineserver -p && wine wineboot
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
--libdir lib
|
||||
--prefix "$(pwd)/build/dav1d_install"
|
||||
--cross-file package/crossfiles/${CROSSFILE}.meson
|
||||
-Ddefault_library=both
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
- cd build && meson test -v
|
||||
- ${CROSSFILE}-nm -A -g src/libdav1d.a | grep " [ABCDGRST] " | (! grep -E -v " \.| _*dav1d_")
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- build/dav1d_install/
|
||||
expire_in: 1 week
|
||||
parallel:
|
||||
matrix:
|
||||
- CROSSFILE: [i686-w64-mingw32, x86_64-w64-mingw32]
|
||||
|
||||
build-win32-unaligned-stack:
|
||||
extends: .debian-llvm-mingw-common
|
||||
script:
|
||||
- wineserver -p && wine wineboot
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
--cross-file package/crossfiles/i686-w64-mingw32.meson
|
||||
-Dstack_alignment=4
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-win-arm:
|
||||
extends: .debian-llvm-mingw-common
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
--libdir lib
|
||||
--prefix "$(pwd)/build/dav1d_install"
|
||||
--cross-file package/crossfiles/${CROSSFILE}.meson
|
||||
-Ddefault_library=both
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
- ${CROSSFILE}-nm -A -g build/src/libdav1d.a | grep " [ABCDGRST] " | (! grep -E -v " \.| _*dav1d_")
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- build/dav1d_install/
|
||||
expire_in: 1 week
|
||||
parallel:
|
||||
matrix:
|
||||
- CROSSFILE: [armv7-w64-mingw32, aarch64-w64-mingw32]
|
||||
|
||||
.build-android-common:
|
||||
extends: .android-common
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
--libdir lib
|
||||
--prefix "$(pwd)/build/dav1d_install"
|
||||
--cross-file $CROSSFILE
|
||||
-Ddefault_library=both
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
|
||||
build-android-armv7:
|
||||
extends: .build-android-common
|
||||
variables:
|
||||
CROSSFILE: package/crossfiles/arm-android.meson
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
|
||||
build-android-aarch64:
|
||||
extends: .build-android-common
|
||||
variables:
|
||||
CROSSFILE: package/crossfiles/aarch64-android.meson
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
|
||||
build-android-armv7-release:
|
||||
extends: build-android-armv7
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG && $CI_PROJECT_PATH == "videolan/dav1d"'
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- build/dav1d_install/
|
||||
expire_in: 1 week
|
||||
|
||||
build-android-aarch64-release:
|
||||
extends: build-android-aarch64
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG && $CI_PROJECT_PATH == "videolan/dav1d"'
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- build/dav1d_install/
|
||||
expire_in: 1 week
|
||||
|
||||
build-debian-aarch64:
|
||||
extends: .debian-aarch64-common
|
||||
script:
|
||||
- meson setup build --buildtype debugoptimized
|
||||
--werror
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-debian-aarch64-clang-5:
|
||||
extends: .debian-aarch64-common
|
||||
variables:
|
||||
CC: clang-5.0
|
||||
CFLAGS: '-integrated-as'
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-debian-aarch64-clang-18:
|
||||
extends: .debian-amd64-common
|
||||
variables:
|
||||
QEMU_LD_PREFIX: /usr/aarch64-linux-gnu/
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtrim_dsp=false
|
||||
--werror
|
||||
--cross-file package/crossfiles/aarch64-linux-clang.meson
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-macos:
|
||||
stage: build
|
||||
tags:
|
||||
- amd64
|
||||
- macos
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Ddefault_library=both
|
||||
-Dtrim_dsp=false
|
||||
--werror
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-debian-werror:
|
||||
extends: .debian-aarch64-common
|
||||
variables:
|
||||
CC: clang
|
||||
script:
|
||||
- meson setup build --buildtype debug
|
||||
--werror
|
||||
- ninja -C build
|
||||
|
||||
build-debian-armv7:
|
||||
extends: .debian-armv7-common
|
||||
script:
|
||||
- linux32 meson setup build --buildtype debugoptimized
|
||||
--werror
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-debian-armv7-clang-5:
|
||||
extends: .debian-armv7-common
|
||||
variables:
|
||||
CC: clang-5.0
|
||||
CFLAGS: '-integrated-as'
|
||||
script:
|
||||
- linux32 meson setup build --buildtype release
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-debian-ppc64le:
|
||||
extends: .debian-ppc64le-common
|
||||
variables:
|
||||
CC: gcc-13
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtrim_dsp=false
|
||||
--werror
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
build-debian-wasm:
|
||||
extends: .debian-wasm-emscripten-common
|
||||
script:
|
||||
- source $EMSCRIPTEN_SDK/emsdk_env.sh
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
--default-library static
|
||||
--cross-file package/crossfiles/${CROSSFILE}.meson
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
parallel:
|
||||
matrix:
|
||||
- CROSSFILE: [wasm32, wasm64]
|
||||
|
||||
build-debian-riscv64:
|
||||
extends: .debian-amd64-common
|
||||
variables:
|
||||
QEMU_CPU: rv64,v=true,vext_spec=v1.0,vlen=256,elen=64
|
||||
QEMU_LD_PREFIX: /usr/riscv64-linux-gnu/
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtrim_dsp=false
|
||||
--werror
|
||||
--cross-file package/crossfiles/${CROSSFILE}.meson
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
parallel:
|
||||
matrix:
|
||||
- CROSSFILE: [riscv64-linux, riscv64-linux-clang]
|
||||
|
||||
build-debian-loongarch64:
|
||||
extends: .debian-amd64-common
|
||||
variables:
|
||||
QEMU_CPU: max-loongarch-cpu
|
||||
QEMU_LD_PREFIX: /opt/cross-tools/target/
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtrim_dsp=false
|
||||
--werror
|
||||
--cross-file package/crossfiles/loongarch64-linux.meson
|
||||
- ninja -C build
|
||||
- cd build && meson test -v
|
||||
|
||||
|
||||
.test-common:
|
||||
stage: test
|
||||
cache:
|
||||
key: testdata.git-20190215
|
||||
paths:
|
||||
- cache/dav1d-test-data.git/
|
||||
before_script:
|
||||
- test -d cache || mkdir cache
|
||||
- test -d cache/dav1d-test-data.git && GIT_DIR=cache/dav1d-test-data.git git fetch --refmap=refs/heads/master:refs/heads/master origin master
|
||||
- test -d cache/dav1d-test-data.git || git clone --bare https://code.videolan.org/videolan/dav1d-test-data.git cache/dav1d-test-data.git
|
||||
- git clone cache/dav1d-test-data.git tests/dav1d-test-data
|
||||
- git -C tests/dav1d-test-data describe --always --long
|
||||
dependencies: []
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
junit: build/meson-logs/testlog.junit.xml
|
||||
|
||||
.test-asm-common:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
tags:
|
||||
- docker
|
||||
- amd64
|
||||
- avx2
|
||||
script:
|
||||
- meson configure build -Dtestdata_tests=true
|
||||
- ninja -C build
|
||||
- cd build
|
||||
- exit_code=0
|
||||
- time meson test -q --suite testdata --test-args "--cpumask 0" || exit_code=$((exit_code + $?))
|
||||
- time meson test -q --suite testdata --test-args "--cpumask sse2" || exit_code=$((exit_code + $?))
|
||||
- time meson test -q --suite testdata --test-args "--cpumask ssse3" || exit_code=$((exit_code + $?))
|
||||
- time meson test -q --suite testdata --test-args "--cpumask sse41" || exit_code=$((exit_code + $?))
|
||||
- time meson test -q --suite testdata --test-args "--cpumask avx2" || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
.test-argon:
|
||||
stage: test
|
||||
cache:
|
||||
key: argon-20230512
|
||||
paths:
|
||||
- cache/argon/
|
||||
variables:
|
||||
ARGON_URL: https://streams.videolan.org/argon/argon.tar.zst
|
||||
before_script:
|
||||
- test -d cache/argon || mkdir -p cache/argon
|
||||
- test -f cache/argon/argon.tar.zst ||
|
||||
(cd cache/argon && curl --remote-name "${ARGON_URL}" --remote-name "${ARGON_URL}.sha512sum" &&
|
||||
sha512sum --check argon.tar.zst.sha512sum )
|
||||
- tar -xf cache/argon/argon.tar.zst -C tests
|
||||
dependencies: []
|
||||
allow_failure: true
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
|
||||
test-debian:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian"]
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Denable_seek_stress=true
|
||||
-Dlogging=false
|
||||
-Db_coverage=true
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v
|
||||
- ninja coverage-html
|
||||
- mv meson-logs/coveragereport ../coverage
|
||||
- ninja coverage-xml
|
||||
- grep -Eo 'line-rate="[^"]+"' meson-logs/coverage.xml | head -n 1 |
|
||||
grep -Eo '[0-9.]+' | awk '{ print "coverage:", $1 * 100 } '
|
||||
- time meson test -v --suite testdata_seek-stress --test-args "--threads 2 --framedelay 1"
|
||||
- time meson test -v --suite testdata_seek-stress --test-args "--threads 2 --framedelay 2"
|
||||
- time meson test -v --suite testdata --test-args "--threads=1 --negstride"
|
||||
coverage: '/^coverage: (\d+.\d+)$/'
|
||||
artifacts:
|
||||
expose_as: 'Coverage HTML report'
|
||||
paths:
|
||||
- coverage/
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: build/meson-logs/coverage.xml
|
||||
|
||||
test-debian-asm:
|
||||
extends:
|
||||
- .test-asm-common
|
||||
needs: ["build-debian"]
|
||||
dependencies: ["build-debian"]
|
||||
|
||||
test-debian32-asm:
|
||||
extends:
|
||||
- .test-asm-common
|
||||
needs: ["build-debian32"]
|
||||
dependencies: ["build-debian32"]
|
||||
|
||||
test-debian-avx512:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
tags:
|
||||
- docker
|
||||
- amd64-avx512
|
||||
variables:
|
||||
CFLAGS: '-mavx'
|
||||
needs: ["build-debian-avx512"]
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && time meson test --suite testdata --test-args "--cpumask avx512icl"
|
||||
- time meson test --suite testdata --test-args "--threads 2 --framedelay 2 --cpumask avx512icl"
|
||||
|
||||
test-debian-unaligned-stack:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian"]
|
||||
tags:
|
||||
- docker
|
||||
- avx2
|
||||
- amd64
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Denable_seek_stress=true
|
||||
-Dlogging=false
|
||||
-Dstack_alignment=16
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v
|
||||
|
||||
test-debian-asan:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian"]
|
||||
variables:
|
||||
ASAN_OPTIONS: 'detect_leaks=0'
|
||||
script:
|
||||
- meson setup build --buildtype debugoptimized
|
||||
-Dtestdata_tests=true
|
||||
-Dlogging=false
|
||||
-Db_sanitize=address
|
||||
- ninja -C build
|
||||
- cd build
|
||||
- exit_code=0
|
||||
- time meson test -v --setup=sanitizer --suite checkasm || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --setup=sanitizer --suite testdata --test-args "--cpumask 0" || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --setup=sanitizer --suite testdata --test-args "--cpumask 0xff" || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
test-debian-msan:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian"]
|
||||
variables:
|
||||
MSAN_OPTIONS: 'exitcode=1'
|
||||
CC: clang
|
||||
script:
|
||||
- meson setup build --buildtype debugoptimized
|
||||
-Dtestdata_tests=true
|
||||
-Denable_seek_stress=true
|
||||
-Dlogging=false
|
||||
-Db_sanitize=memory
|
||||
-Db_lundef=false
|
||||
-Denable_asm=false
|
||||
- ninja -C build
|
||||
- cd build
|
||||
- exit_code=0
|
||||
- time meson test -v --setup=sanitizer || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --setup=sanitizer --suite testdata --test-args "--frametimes /dev/null" || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
test-debian-ubsan:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian"]
|
||||
variables:
|
||||
UBSAN_OPTIONS: 'print_stacktrace=1:halt_on_error=1'
|
||||
CC: clang
|
||||
script:
|
||||
- meson setup build --buildtype debugoptimized
|
||||
-Dtestdata_tests=true
|
||||
-Denable_seek_stress=true
|
||||
-Dlogging=false
|
||||
-Db_sanitize=undefined
|
||||
-Db_lundef=false
|
||||
-Denable_asm=false
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v --setup=sanitizer
|
||||
|
||||
test-debian-tsan:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian"]
|
||||
variables:
|
||||
TSAN_OPTIONS: 'halt_on_error=1'
|
||||
CC: clang
|
||||
script:
|
||||
- meson setup build --buildtype debugoptimized
|
||||
-Dtestdata_tests=true
|
||||
-Denable_seek_stress=true
|
||||
-Dlogging=false
|
||||
-Db_sanitize=thread
|
||||
-Db_lundef=false
|
||||
- ninja -C build
|
||||
- cd build
|
||||
- exit_code=0
|
||||
- time meson test -v --setup=sanitizer --suite testdata --test-args "--threads 2 --framedelay 1" || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --setup=sanitizer --suite testdata --test-args "--threads 2 --framedelay 2" || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --setup=sanitizer --suite testdata --test-args "--threads 2 --framedelay 2 --negstride" || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --setup=sanitizer --suite testdata_seek-stress --test-args "--threads 2 --framedelay 1" || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --setup=sanitizer --suite testdata_seek-stress --test-args "--threads 2 --framedelay 2" || exit_code=$((exit_code + $?))
|
||||
- time meson test -v --setup=sanitizer --suite oss-fuzz-asan --suite oss-fuzz-msan --suite oss-fuzz-ubsan || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
test-win64:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-win: [x86_64-w64-mingw32]"]
|
||||
tags:
|
||||
- docker
|
||||
- avx2
|
||||
- amd64
|
||||
script:
|
||||
- wineserver -p && wine wineboot
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
--cross-file package/crossfiles/x86_64-w64-mingw32.meson
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v
|
||||
|
||||
test-debian-aarch64:
|
||||
extends:
|
||||
- .debian-aarch64-common
|
||||
- .test-common
|
||||
needs: ["build-debian-aarch64"]
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v
|
||||
|
||||
test-debian-ppc64le:
|
||||
extends:
|
||||
- .debian-ppc64le-common
|
||||
- .test-common
|
||||
variables:
|
||||
CC: gcc-13
|
||||
needs: ["build-debian-ppc64le"]
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v
|
||||
|
||||
test-debian-riscv64:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian-riscv64"]
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
--cross-file package/crossfiles/riscv64-linux.meson
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v --timeout-multiplier 10
|
||||
variables:
|
||||
QEMU_LD_PREFIX: /usr/riscv64-linux-gnu/
|
||||
parallel:
|
||||
matrix:
|
||||
- QEMU_CPU: [ "rv64,v=true,vext_spec=v1.0,vlen=128,elen=64",
|
||||
"rv64,v=true,vext_spec=v1.0,vlen=256,elen=64",
|
||||
"rv64,v=true,vext_spec=v1.0,vlen=512,elen=64",
|
||||
"rv64,v=true,vext_spec=v1.0,vlen=1024,elen=64" ]
|
||||
|
||||
test-debian-aarch64-qemu:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian-aarch64"]
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
--cross-file package/crossfiles/aarch64-linux.meson
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v --timeout-multiplier 10
|
||||
variables:
|
||||
QEMU_LD_PREFIX: /usr/aarch64-linux-gnu/
|
||||
parallel:
|
||||
matrix:
|
||||
# sve-default-vector-length sets the max vector length in bytes;
|
||||
# the default is 64, allowing up to 512 bit vectors. Testing 1024
|
||||
# and 2048 bit vectors requires raising this limit. The sve<n>
|
||||
# option sets the active vector length in bits.
|
||||
- QEMU_CPU: [ "max,sve-default-vector-length=256,sve128=on",
|
||||
"max,sve-default-vector-length=256,sve256=on",
|
||||
"max,sve-default-vector-length=256,sve512=on",
|
||||
"max,sve-default-vector-length=256,sve1024=on",
|
||||
"max,sve-default-vector-length=256,sve2048=on" ]
|
||||
|
||||
test-debian-armv7-clang-5:
|
||||
extends:
|
||||
- .debian-armv7-common
|
||||
- .test-common
|
||||
needs: ["build-debian-armv7-clang-5"]
|
||||
variables:
|
||||
CC: clang-5.0
|
||||
CFLAGS: '-integrated-as'
|
||||
script:
|
||||
- linux32 meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v
|
||||
|
||||
test-debian-loongarch64:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-common
|
||||
needs: ["build-debian-loongarch64"]
|
||||
variables:
|
||||
QEMU_CPU: max-loongarch-cpu
|
||||
QEMU_LD_PREFIX: /opt/cross-tools/target/
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dtestdata_tests=true
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
--cross-file package/crossfiles/loongarch64-linux.meson
|
||||
- ninja -C build
|
||||
- cd build && time meson test -v --timeout-multiplier 10
|
||||
|
||||
.test-argon-script: &test-argon-script
|
||||
- meson setup build --buildtype release
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
- cd build && ninja
|
||||
- exit_code=0
|
||||
|
||||
test-debian-argon:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-argon
|
||||
needs: ["build-debian"]
|
||||
tags:
|
||||
- docker
|
||||
- amd64
|
||||
- avx2
|
||||
script:
|
||||
- *test-argon-script
|
||||
- ../tests/dav1d_argon.bash -t 1 -c 0 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 2 -c sse2 -g 0 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 3 -c ssse3 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 4 -c sse41 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 5 -c avx2 || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
test-debian32-argon:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-argon
|
||||
needs: ["build-debian32"]
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
-Dlogging=false
|
||||
-Dtrim_dsp=false
|
||||
--cross-file package/crossfiles/i686-linux32.meson
|
||||
- cd build && ninja
|
||||
- exit_code=0
|
||||
- ../tests/dav1d_argon.bash -t 2 -c sse2 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 2 -c ssse3 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 2 -c sse41 -g 0 || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
test-debian-argon-avx512:
|
||||
extends:
|
||||
- .debian-amd64-common
|
||||
- .test-argon
|
||||
needs: ["build-debian-avx512"]
|
||||
tags:
|
||||
- docker
|
||||
- amd64-avx512
|
||||
script:
|
||||
- *test-argon-script
|
||||
- ../tests/dav1d_argon.bash -t 2 -c avx512icl || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
test-debian-armv7-argon:
|
||||
extends:
|
||||
- .debian-armv7-common
|
||||
- .test-argon
|
||||
needs: ["build-debian-armv7"]
|
||||
script:
|
||||
- *test-argon-script
|
||||
- ../tests/dav1d_argon.bash -t 3 -c 0 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 2 -c neon || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 1 -c neon -g 0 || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
test-debian-aarch64-argon:
|
||||
extends:
|
||||
- .debian-aarch64-common
|
||||
- .test-argon
|
||||
needs: ["build-debian-aarch64"]
|
||||
tags:
|
||||
- docker
|
||||
- aarch64
|
||||
- dotprod
|
||||
script:
|
||||
- *test-argon-script
|
||||
- ../tests/dav1d_argon.bash -t 2 -c 0 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 3 -c neon || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 1 -c neon -g 0 || exit_code=$((exit_code + $?))
|
||||
- ../tests/dav1d_argon.bash -t 4 -c dotprod || exit_code=$((exit_code + $?))
|
||||
- if [ $exit_code -ne 0 ]; then exit $exit_code; fi
|
||||
|
||||
|
||||
.pages-common:
|
||||
extends: .debian-amd64-common
|
||||
script:
|
||||
- meson setup build --buildtype release
|
||||
--werror
|
||||
-Denable_docs=true
|
||||
- ninja -C build doc/html
|
||||
- mv build/doc/html public
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
|
||||
build-pages:
|
||||
extends: .pages-common
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
|
||||
|
||||
pages:
|
||||
extends: .pages-common
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
changes:
|
||||
- include/dav1d/*
|
||||
- doc/meson.build
|
||||
- doc/Doxyfile.in.in
|
||||
56
media/libdav1d/src/CONTRIBUTING.md
Normal file
56
media/libdav1d/src/CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# dav1d contribution guide
|
||||
|
||||
## CoC
|
||||
The [VideoLAN Code of Conduct](https://wiki.videolan.org/CoC) applies fully to this project.
|
||||
|
||||
## ToDo
|
||||
|
||||
The todo list can be found [on the wiki](https://code.videolan.org/videolan/dav1d/wikis/task-list).
|
||||
|
||||
## Codebase language
|
||||
|
||||
The codebase is developed with the following assumptions:
|
||||
|
||||
For the library:
|
||||
- C language with C99 version, without the VLA or the Complex (*\_\_STDC_NO_COMPLEX__*) features, and without compiler extensions. Anonymous structures and unions are the only allowed compiler extensions for internal code.
|
||||
- x86 asm in .asm files, using the NASM syntax,
|
||||
- arm/arm64 in .S files, using the GAS syntax limited to subset llvm 5.0's internal assembler supports,
|
||||
- no C++ is allowed, whatever the version.
|
||||
|
||||
For the tools and utils:
|
||||
- C *(see above for restrictions)*
|
||||
- Rust
|
||||
- C++ is only allowed for the MFT.
|
||||
|
||||
If you want to use *Threads* or *Atomic* features, please conform to the **C11**/**POSIX** semantic and use a wrapper for older compilers/platforms *(like done in VLC)*.
|
||||
|
||||
Please use modern standard POSIX functions *(strscpy, asprintf, tdestroy)*, and provide a compatibility fallback *(like done in VLC)*.
|
||||
|
||||
We will make reasonable efforts for compilers that are a bit older, but we won't support gcc 3 or MSVC 2012.
|
||||
|
||||
## Authorship
|
||||
|
||||
Please provide a correct authorship for your commit logs, with a name and a valid email.
|
||||
|
||||
We will reject anonymous contributions for now. As an exception, known pseudonyms from the multimedia community are accepted.
|
||||
|
||||
This project is respecting **Copyright** and **Droit d'auteur**. There is no copyright attribution or CLA.
|
||||
|
||||
## Commit logs
|
||||
|
||||
Please read [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/).
|
||||
|
||||
## Submit requests (WIP)
|
||||
|
||||
- Code,
|
||||
- [Compile](https://xkcd.com/303/),
|
||||
- Check your [code style](https://code.videolan.org/videolan/dav1d/wikis/Coding-style),
|
||||
- Test,
|
||||
- Try,
|
||||
- Submit patches through merge requests,
|
||||
- Check that this passes the CI.
|
||||
|
||||
## Patent license
|
||||
|
||||
You need to read, understand, and agree to the [AV1 patents license](doc/PATENTS), before committing.
|
||||
|
||||
23
media/libdav1d/src/COPYING
Normal file
23
media/libdav1d/src/COPYING
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Copyright © 2018-2025, VideoLAN and dav1d authors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
460
media/libdav1d/src/NEWS
Normal file
460
media/libdav1d/src/NEWS
Normal file
|
|
@ -0,0 +1,460 @@
|
|||
Changes for 1.5.3 'Sonic':
|
||||
--------------------------
|
||||
|
||||
1.5.3 is a minor release of dav1d, focused on RISC-V and maintenance:
|
||||
- Misc small optimizations
|
||||
- RISC-V assembly optimizations for ipred, emu_edge and w_mask,
|
||||
and VLEN 512 for blend functions
|
||||
- Fix issue with ivf files with 0 frames in tools
|
||||
|
||||
|
||||
Changes for 1.5.2 'Sonic':
|
||||
--------------------------
|
||||
|
||||
1.5.2 is a minor release of dav1d, focused on maintenance:
|
||||
- minor speed improvement in recon
|
||||
- improvements on loongarch symboles visibility and asm
|
||||
- mark C globals with small code model
|
||||
- reduce the code size of the frame header parsing (OBU)
|
||||
- minor fixes on tools and CI
|
||||
- fix compilation with nasm 3.00
|
||||
|
||||
|
||||
Changes for 1.5.1 'Sonic':
|
||||
--------------------------
|
||||
|
||||
1.5.1 is a minor release of dav1d, focusing on optimizations and stack reduction:
|
||||
|
||||
- Rewrite of the looprestoration (SGR, wiener) to reduce stack usage
|
||||
- Rewrite of {put,prep}_scaled functions
|
||||
|
||||
Now, the required stack space for dav1d should be: 62 KB on x86_64 and
|
||||
58KB on arm and aarch64.
|
||||
|
||||
- Improvements on the SSSE3 SGR
|
||||
- Improvements on ARM32/ARM64 looprestoration optimizations
|
||||
- RISC-V: blend optimizations for high bitdepth
|
||||
- Power9: blend optimizations for 8bpc
|
||||
- Port RISC-V to POSIX/non-Linux OS
|
||||
- AArch64: Add Neon implementation of load_tmvs
|
||||
- Fix a rare, but possible deadlock, in flush()
|
||||
|
||||
|
||||
Changes for 1.5.0 'Sonic':
|
||||
--------------------------
|
||||
|
||||
1.5.0 is a major release of dav1d, that:
|
||||
- WARNING: we removed some of the SSE2 optimizations, so if you care about
|
||||
systems without SSSE3, you should be careful when updating!
|
||||
- Add Arm OpenBSD run-time CPU feature
|
||||
- Optimize index offset calculations for decode_coefs
|
||||
- picture: copy HDR10+ and T35 metadata only to visible frames
|
||||
- SSSE3 new optimizations for 6-tap (8bit and hbd)
|
||||
- AArch64/SVE: Add HBD subpel filters using 128-bit SVE2
|
||||
- AArch64: Add USMMLA Implementation for 6-tap H/HV
|
||||
- AArch64: Optimize Armv8.0 NEON for HBD horizontal filters and 6-tap filters
|
||||
- Power9: Optimized ITX till 16x4.
|
||||
- Loongarch: numerous optimizations
|
||||
- RISC-V optimizations for pal, cdef_filter, ipred, mc_blend, mc_bdir, itx
|
||||
- Allow playing videos in full-screen mode in dav1dplay
|
||||
|
||||
|
||||
Changes for 1.4.3 'Road Runner':
|
||||
--------------------------------
|
||||
|
||||
1.4.3 is a small release focused on security issues
|
||||
- AArch64: Fix potential out of bounds access in DotProd H/HV filters
|
||||
- cli: Prevent buffer over-read
|
||||
|
||||
|
||||
Changes for 1.4.2 'Road Runner':
|
||||
--------------------------------
|
||||
|
||||
1.4.2 is a small release of dav1d, improving notably ARM, AVX-512 and PowerPC
|
||||
- AVX2 optimizations for 8-tap and new variants for 6-tap
|
||||
- AVX-512 optimizations for 8-tap and new variants for 6-tap
|
||||
- Improve entropy decoding on ARM64
|
||||
- New ARM64 optimizations for convolutions based on DotProd extension
|
||||
- New ARM64 optimizations for convolutions based on i8mm extension
|
||||
- New ARM64 optimizations for subpel and prep filters for i8mm
|
||||
- Misc improvements on existing ARM64 optimizations, notably for put/prep
|
||||
- New PowerPC9 optimizations for loopfilter
|
||||
- Support for macOS kperf API for benchmarking
|
||||
|
||||
|
||||
Changes for 1.4.1 'Road Runner':
|
||||
--------------------------------
|
||||
|
||||
1.4.1 is a small release of dav1d, improving notably ARM and RISC-V speed
|
||||
|
||||
- Optimizations for 6tap filters for NEON (ARM)
|
||||
- More RISC-V optimizations for itx (4x8, 8x4, 4x16, 16x4, 8x16, 16x8)
|
||||
- Reduction of binary size on ARM64, ARM32 and RISC-V
|
||||
- Fix out-of-bounds read in 8bpc SSE2/SSSE3 wiener_filter
|
||||
- Msac optimizations
|
||||
|
||||
|
||||
Changes for 1.4.0 'Road Runner':
|
||||
--------------------------------
|
||||
|
||||
1.4.0 is a medium release of dav1d, focusing on new architecture support and optimizations
|
||||
|
||||
- AVX-512 optimizations for z1, z2, z3 in 8bit and high-bitdepth
|
||||
- New architecture supported: loongarch
|
||||
- Loongarch optimizations for 8bit
|
||||
- New architecture supported: RISC-V
|
||||
- RISC-V optimizations for itx
|
||||
- Misc improvements in threading and in reducing binary size
|
||||
- Fix potential integer overflow with extremely large frame sizes (CVE-2024-1580)
|
||||
|
||||
|
||||
Changes for 1.3.0 'Tundra Peregrine Falcon (Calidus)':
|
||||
------------------------------------------------------
|
||||
|
||||
1.3.0 is a medium release of dav1d, focus on new APIs and memory usage reduction.
|
||||
|
||||
- Reduce memory usage in numerous places
|
||||
- ABI break in Dav1dSequenceHeader, Dav1dFrameHeader, Dav1dContentLightLevel structures
|
||||
- new API function to check the API version: dav1d_version_api()
|
||||
- Rewrite of the SGR functions for ARM64 to be faster
|
||||
- NEON implemetation of save_tmvs for ARM32 and ARM64
|
||||
- x86 palette DSP for pal_idx_finish function
|
||||
|
||||
|
||||
Changes for 1.2.1 'Arctic Peregrine Falcon':
|
||||
--------------------------------------------
|
||||
|
||||
1.2.1 is a small release of dav1d, adding more SIMD and fixes
|
||||
|
||||
- Fix a threading race on task_thread.init_done
|
||||
- NEON z2 8bpc and high bit-depth optimizations
|
||||
- SSSE3 z2 high bit-depth optimziations
|
||||
- Fix a desynced luma/chroma planes issue with Film Grain
|
||||
- Reduce memory consumption
|
||||
- Improve dav1d_parse_sequence_header() speed
|
||||
- OBU: Improve header parsing and fix potential overflows
|
||||
- OBU: Improve ITU-T T.35 parsing speed
|
||||
- Misc buildsystems, CI and headers fixes
|
||||
|
||||
|
||||
Changes for 1.2.0 'Arctic Peregrine Falcon':
|
||||
--------------------------------------------
|
||||
|
||||
1.2.0 is a small release of dav1d, adding more SIMD and fixes
|
||||
|
||||
- Improvements on attachments of props and T.35 entries on output pictures
|
||||
- NEON z1/z3 high bit-depth optimizations and improvements for 8bpc
|
||||
- SSSE3 z2/z3 8bpc and SSSE3 z1/z3 high bit-depth optimziations
|
||||
- refmvs.save_tmvs optimizations in SSSE3/AVX2/AVX-512
|
||||
- AVX-512 optimizations for high bit-depth itx (16x64, 32x64, 64x16, 64x32, 64x64)
|
||||
- AVX2 optimizations for 12bpc for 16x32, 32x16, 32x32 itx
|
||||
|
||||
|
||||
Changes for 1.1.0 'Arctic Peregrine Falcon':
|
||||
--------------------------------------------
|
||||
|
||||
1.1.0 is an important release of dav1d, fixing numerous bugs, and adding SIMD
|
||||
|
||||
- New function dav1d_get_frame_delay to query the decoder frame delay
|
||||
- Numerous fixes for strict conformity to the specs and samples
|
||||
- NEON and AVX-512 misc fixes and improvements
|
||||
- Partial AVX2 12bpc transform implementations
|
||||
- AVX-512 high bit-depth cdef_filter, loopfilter, itx
|
||||
- NEON z1/z3 optimization for 8bpc
|
||||
- SSSE3 z1 optimization for 8bpc
|
||||
|
||||
"From VideoLAN with love"
|
||||
|
||||
|
||||
Changes for 1.0.0 'Peregrine Falcon':
|
||||
-------------------------------------
|
||||
|
||||
1.0.0 is a major release of dav1d, adding important features and bug fixes.
|
||||
|
||||
It notably changes, in an important way, the way threading works, by adding
|
||||
an automatic thread management.
|
||||
|
||||
It also adds support for AVX-512 acceleration, and adds speedups to existing x86
|
||||
code (from SSE2 to AVX2).
|
||||
|
||||
1.0.0 adds new grain API to ease acceleration on the GPU, and adds an API call
|
||||
to get information of which frame failed to decode, in error cases.
|
||||
|
||||
Finally, 1.0.0 fixes numerous small bugs that were reported since the beginning
|
||||
of the project to have a proper release.
|
||||
|
||||
.''.
|
||||
.''. . *''* :_\/_: .
|
||||
:_\/_: _\(/_ .:.*_\/_* : /\ : .'.:.'.
|
||||
.''.: /\ : ./)\ ':'* /\ * : '..'. -=:o:=-
|
||||
:_\/_:'.:::. ' *''* * '.\'/.' _\(/_'.':'.'
|
||||
: /\ : ::::: *_\/_* -= o =- /)\ ' *
|
||||
'..' ':::' * /\ * .'/.\'. '
|
||||
* *..* :
|
||||
* :
|
||||
* 1.0.0
|
||||
|
||||
|
||||
|
||||
Changes for 0.9.2 'Golden Eagle':
|
||||
---------------------------------
|
||||
|
||||
0.9.2 is a small update of dav1d on the 0.9.x branch:
|
||||
- x86: SSE4 optimizations of inverse transforms for 10bit for all sizes
|
||||
- x86: mc.resize optimizations with AVX2/SSSE3 for 10/12b
|
||||
- x86: SSSE3 optimizations for cdef_filter in 10/12b and mc_w_mask_422/444 in 8b
|
||||
- ARM NEON optimizations for FilmGrain Gen_grain functions
|
||||
- Optimizations for splat_mv in SSE2/AVX2 and NEON
|
||||
- x86: SGR improvements for SSSE3 CPUs
|
||||
- x86: AVX2 optimizations for cfl_ac
|
||||
|
||||
|
||||
Changes for 0.9.1 'Golden Eagle':
|
||||
---------------------------------
|
||||
|
||||
0.9.1 is a middle-size revision of dav1d, adding notably 10b acceleration for SSSE3:
|
||||
- 10/12b SSSE3 optimizations for mc (avg, w_avg, mask, w_mask, emu_edge),
|
||||
prep/put_bilin, prep/put_8tap, ipred (dc/h/v, paeth, smooth, pal, filter), wiener,
|
||||
sgr (10b), warp8x8, deblock, film_grain, cfl_ac/pred for 32bit and 64bit x86 processors
|
||||
- Film grain NEON for fguv 10/12b, fgy/fguv 8b and fgy/fguv 10/12 arm32
|
||||
- Fixes for filmgrain on ARM
|
||||
- itx 10bit optimizations for 4x4/x8/x16, 8x4/x8/x16 for SSE4
|
||||
- Misc improvements on SSE2, SSE4
|
||||
|
||||
|
||||
Changes for 0.9.0 'Golden Eagle':
|
||||
---------------------------------
|
||||
|
||||
0.9.0 is a major version of dav1d, adding notably 10b acceleration on x64.
|
||||
|
||||
Details:
|
||||
- x86 (64bit) AVX2 implementation of most 10b/12b functions, which should provide
|
||||
a large boost for high-bitdepth decoding on modern x86 computers and servers.
|
||||
- ARM64 neon implementation of FilmGrain (4:2:0/4:2:2/4:4:4 8bit)
|
||||
- New API to signal events happening during the decoding process
|
||||
|
||||
|
||||
Changes for 0.8.2 'Eurasian Hobby':
|
||||
-----------------------------------
|
||||
|
||||
0.8.2 is a middle-size update of the 0.8.0 branch:
|
||||
- ARM32 optimizations for ipred and itx in 10/12bits,
|
||||
completing the 10b/12b work on ARM64 and ARM32
|
||||
- Give the post-filters their own threads
|
||||
- ARM64: rewrite the wiener functions
|
||||
- Speed up coefficient decoding, 0.5%-3% global decoding gain
|
||||
- x86 optimizations for CDEF_filter and wiener in 10/12bit
|
||||
- x86: rewrite the SGR AVX2 asm
|
||||
- x86: improve msac speed on SSE2+ machines
|
||||
- ARM32: improve speed of ipred and warp
|
||||
- ARM64: improve speed of ipred, cdef_dir, cdef_filter, warp_motion and itx16
|
||||
- ARM32/64: improve speed of looprestoration
|
||||
- Add seeking, pausing to the player
|
||||
- Update the player for rendering of 10b/12b
|
||||
- Misc speed improvements and fixes on all platforms
|
||||
- Add a xxh3 muxer in the dav1d application
|
||||
|
||||
|
||||
Changes for 0.8.1 'Eurasian Hobby':
|
||||
-----------------------------------
|
||||
|
||||
0.8.1 is a minor update on 0.8.0:
|
||||
- Keep references to buffers valid after dav1d_close(). Fixes a regression
|
||||
caused by the picture buffer pool added in 0.8.0.
|
||||
- ARM32 optimizations for 10bit bitdepth for SGR
|
||||
- ARM32 optimizations for 16bit bitdepth for blend/w_masl/emu_edge
|
||||
- ARM64 optimizations for 10bit bitdepth for SGR
|
||||
- x86 optimizations for wiener in SSE2/SSSE3/AVX2
|
||||
|
||||
|
||||
Changes for 0.8.0 'Eurasian Hobby':
|
||||
-----------------------------------
|
||||
|
||||
0.8.0 is a major update for dav1d:
|
||||
- Improve the performance by using a picture buffer pool;
|
||||
The improvements can reach 10% on some cases on Windows.
|
||||
- Support for Apple ARM Silicon
|
||||
- ARM32 optimizations for 8bit bitdepth for ipred paeth, smooth, cfl
|
||||
- ARM32 optimizations for 10/12/16bit bitdepth for mc_avg/mask/w_avg,
|
||||
put/prep 8tap/bilin, wiener and CDEF filters
|
||||
- ARM64 optimizations for cfl_ac 444 for all bitdepths
|
||||
- x86 optimizations for MC 8-tap, mc_scaled in AVX2
|
||||
- x86 optimizations for CDEF in SSE and {put/prep}_{8tap/bilin} in SSSE3
|
||||
|
||||
|
||||
Changes for 0.7.1 'Frigatebird':
|
||||
------------------------------
|
||||
|
||||
0.7.1 is a minor update on 0.7.0:
|
||||
- ARM32 NEON optimizations for itxfm, which can give up to 28% speedup, and MSAC
|
||||
- SSE2 optimizations for prep_bilin and prep_8tap
|
||||
- AVX2 optimizations for MC scaled
|
||||
- Fix a clamping issue in motion vector projection
|
||||
- Fix an issue on some specific Haswell CPU on ipred_z AVX2 functions
|
||||
- Improvements on the dav1dplay utility player to support resizing
|
||||
|
||||
|
||||
Changes for 0.7.0 'Frigatebird':
|
||||
------------------------------
|
||||
|
||||
0.7.0 is a major release for dav1d:
|
||||
- Faster refmv implementation gaining up to 12% speed while -25% of RAM (Single Thread)
|
||||
- 10b/12b ARM64 optimizations are mostly complete:
|
||||
- ipred (paeth, smooth, dc, pal, filter, cfl)
|
||||
- itxfm (only 10b)
|
||||
- AVX2/SSSE3 for non-4:2:0 film grain and for mc.resize
|
||||
- AVX2 for cfl4:4:4
|
||||
- AVX-512 CDEF filter
|
||||
- ARM64 8b improvements for cfl_ac and itxfm
|
||||
- ARM64 implementation for emu_edge in 8b/10b/12b
|
||||
- ARM32 implementation for emu_edge in 8b
|
||||
- Improvements on the dav1dplay utility player to support 10 bit,
|
||||
non-4:2:0 pixel formats and film grain on the GPU
|
||||
|
||||
|
||||
Changes for 0.6.0 'Gyrfalcon':
|
||||
------------------------------
|
||||
|
||||
0.6.0 is a major release for dav1d:
|
||||
- New ARM64 optimizations for the 10/12bit depth:
|
||||
- mc_avg, mc_w_avg, mc_mask
|
||||
- mc_put/mc_prep 8tap/bilin
|
||||
- mc_warp_8x8
|
||||
- mc_w_mask
|
||||
- mc_blend
|
||||
- wiener
|
||||
- SGR
|
||||
- loopfilter
|
||||
- cdef
|
||||
- New AVX-512 optimizations for prep_bilin, prep_8tap, cdef_filter, mc_avg/w_avg/mask
|
||||
- New SSSE3 optimizations for film grain
|
||||
- New AVX2 optimizations for msac_adapt16
|
||||
- Fix rare mismatches against the reference decoder, notably because of clipping
|
||||
- Improvements on ARM64 on msac, cdef, mc_blend_v and looprestoration optimizations
|
||||
- Improvements on AVX2 optimizations for cdef_filter
|
||||
- Improvements in the C version for itxfm, cdef_filter
|
||||
|
||||
|
||||
Changes for 0.5.2 'Asiatic Cheetah':
|
||||
------------------------------------
|
||||
|
||||
0.5.2 is a small release improving speed for ARM32 and adding minor features:
|
||||
- ARM32 optimizations for loopfilter, ipred_dc|h|v
|
||||
- Add section-5 raw OBU demuxer
|
||||
- Improve the speed by reducing the L2 cache collisions
|
||||
- Fix minor issues
|
||||
|
||||
|
||||
Changes for 0.5.1 'Asiatic Cheetah':
|
||||
------------------------------------
|
||||
|
||||
0.5.1 is a small release improving speeds and fixing minor issues
|
||||
compared to 0.5.0:
|
||||
- SSE2 optimizations for CDEF, wiener and warp_affine
|
||||
- NEON optimizations for SGR on ARM32
|
||||
- Fix mismatch issue in x86 asm in inverse identity transforms
|
||||
- Fix build issue in ARM64 assembly if debug info was enabled
|
||||
- Add a workaround for Xcode 11 -fstack-check bug
|
||||
|
||||
|
||||
Changes for 0.5.0 'Asiatic Cheetah':
|
||||
------------------------------------
|
||||
|
||||
0.5.0 is a medium release fixing regressions and minor issues,
|
||||
and improving speed significantly:
|
||||
- Export ITU T.35 metadata
|
||||
- Speed improvements on blend_ on ARM
|
||||
- Speed improvements on decode_coef and MSAC
|
||||
- NEON optimizations for blend*, w_mask_, ipred functions for ARM64
|
||||
- NEON optimizations for CDEF and warp on ARM32
|
||||
- SSE2 optimizations for MSAC hi_tok decoding
|
||||
- SSSE3 optimizations for deblocking loopfilters and warp_affine
|
||||
- AVX2 optimizations for film grain and ipred_z2
|
||||
- SSE4 optimizations for warp_affine
|
||||
- VSX optimizations for wiener
|
||||
- Fix inverse transform overflows in x86 and NEON asm
|
||||
- Fix integer overflows with large frames
|
||||
- Improve film grain generation to match reference code
|
||||
- Improve compatibility with older binutils for ARM
|
||||
- More advanced Player example in tools
|
||||
|
||||
|
||||
Changes for 0.4.0 'Cheetah':
|
||||
----------------------------
|
||||
|
||||
- Fix playback with unknown OBUs
|
||||
- Add an option to limit the maximum frame size
|
||||
- SSE2 and ARM64 optimizations for MSAC
|
||||
- Improve speed on 32bits systems
|
||||
- Optimization in obmc blend
|
||||
- Reduce RAM usage significantly
|
||||
- The initial PPC SIMD code, cdef_filter
|
||||
- NEON optimizations for blend functions on ARM
|
||||
- NEON optimizations for w_mask functions on ARM
|
||||
- NEON optimizations for inverse transforms on ARM64
|
||||
- VSX optimizations for CDEF filter
|
||||
- Improve handling of malloc failures
|
||||
- Simple Player example in tools
|
||||
|
||||
|
||||
Changes for 0.3.1 'Sailfish':
|
||||
------------------------------
|
||||
|
||||
- Fix a buffer overflow in frame-threading mode on SSSE3 CPUs
|
||||
- Reduce binary size, notably on Windows
|
||||
- SSSE3 optimizations for ipred_filter
|
||||
- ARM optimizations for MSAC
|
||||
|
||||
|
||||
Changes for 0.3.0 'Sailfish':
|
||||
------------------------------
|
||||
|
||||
This is the final release for the numerous speed improvements of 0.3.0-rc.
|
||||
It mostly:
|
||||
- Fixes an annoying crash on SSSE3 that happened in the itx functions
|
||||
|
||||
|
||||
Changes for 0.2.2 (0.3.0-rc) 'Antelope':
|
||||
-----------------------------
|
||||
|
||||
- Large improvement on MSAC decoding with SSE, bringing 4-6% speed increase
|
||||
The impact is important on SSSE3, SSE4 and AVX2 cpus
|
||||
- SSSE3 optimizations for all blocks size in itx
|
||||
- SSSE3 optimizations for ipred_paeth and ipred_cfl (420, 422 and 444)
|
||||
- Speed improvements on CDEF for SSE4 CPUs
|
||||
- NEON optimizations for SGR and loop filter
|
||||
- Minor crashes, improvements and build changes
|
||||
|
||||
|
||||
Changes for 0.2.1 'Antelope':
|
||||
----------------------------
|
||||
|
||||
- SSSE3 optimization for cdef_dir
|
||||
- AVX2 improvements of the existing CDEF optimizations
|
||||
- NEON improvements of the existing CDEF and wiener optimizations
|
||||
- Clarification about the numbering/versionning scheme
|
||||
|
||||
|
||||
Changes for 0.2.0 'Antelope':
|
||||
----------------------------
|
||||
|
||||
- ARM64 and ARM optimizations using NEON instructions
|
||||
- SSSE3 optimizations for both 32 and 64bits
|
||||
- More AVX2 assembly, reaching almost completion
|
||||
- Fix installation of includes
|
||||
- Rewrite inverse transforms to avoid overflows
|
||||
- Snap packaging for Linux
|
||||
- Updated API (ABI and API break)
|
||||
- Fixes for un-decodable samples
|
||||
|
||||
|
||||
Changes for 0.1.0 'Gazelle':
|
||||
----------------------------
|
||||
|
||||
Initial release of dav1d, the fast and small AV1 decoder.
|
||||
- Support for all features of the AV1 bitstream
|
||||
- Support for all bitdepth, 8, 10 and 12bits
|
||||
- Support for all chroma subsamplings 4:2:0, 4:2:2, 4:4:4 *and* grayscale
|
||||
- Full acceleration for AVX2 64bits processors, making it the fastest decoder
|
||||
- Partial acceleration for SSSE3 processors
|
||||
- Partial acceleration for NEON processors
|
||||
168
media/libdav1d/src/README.md
Normal file
168
media/libdav1d/src/README.md
Normal file
|
|
@ -0,0 +1,168 @@
|
|||

|
||||
|
||||
# dav1d
|
||||
|
||||
**dav1d** is an **AV1** cross-platform **d**ecoder, open-source, and focused on speed and correctness.
|
||||
|
||||
It is now battle-tested and production-ready and can be used everywhere.
|
||||
|
||||
The canonical repository URL for this repo is https://code.videolan.org/videolan/dav1d
|
||||
|
||||
This project was partially funded by the *Alliance for Open Media*/**AOM**.
|
||||
|
||||
## Goal and Features
|
||||
|
||||
The goal of this project is to provide a decoder for **most platforms**, and achieve the **highest speed** possible to overcome the temporary lack of AV1 hardware decoder.
|
||||
|
||||
It supports all features from AV1, including all subsampling and bit-depth parameters.
|
||||
|
||||
In the future, this project will host simple tools or simple wrappings *(like, for example, an MFT transform)*.
|
||||
|
||||
## License
|
||||
|
||||
**dav1d** is released under a very liberal license, a contrario from the other VideoLAN projects, so that it can be embedded anywhere, including non-open-source software; or even drivers, to allow the creation of hybrid decoders.
|
||||
|
||||
The reasoning behind this decision is the same as for libvorbis, see [RMS on vorbis](https://lwn.net/2001/0301/a/rms-ov-license.php3).
|
||||
|
||||
# Roadmap
|
||||
|
||||
The plan is the following:
|
||||
|
||||
### Reached
|
||||
1. Complete C implementation of the decoder,
|
||||
2. Provide a usable API,
|
||||
3. Port to most platforms,
|
||||
4. Make it fast on desktop, by writing asm for AVX2 chips.
|
||||
5. Make it fast on mobile, by writing asm for ARMv8 chips,
|
||||
6. Make it fast on older desktop, by writing asm for SSSE3+ chips,
|
||||
7. Make high bit-depth fast on mobile, by writing asm for ARMv8 chips.
|
||||
8. Make it fast on older mobile, by writing asm for ARMv7 chips,
|
||||
9. Make high bit-depth fast on older mobile, by writing asm for ARMv7 chips,
|
||||
10. Make high bit-depth fast on desktop, by writing asm for AVX2 chips,
|
||||
11. Make high bit-depth fast on older desktop, by writing asm for SSSE3+ chips,
|
||||
12. Improve threading.
|
||||
|
||||
### On-going
|
||||
13. Improve C code base with [various tweaks](https://code.videolan.org/videolan/dav1d/wikis/task-list),
|
||||
14. Accelerate for less common architectures, like PPC, SSE2, RISC-V or AVX-512.
|
||||
|
||||
### After
|
||||
15. Use more GPU decoding, when possible.
|
||||
|
||||
# Contribute
|
||||
|
||||
Currently, we are looking for help from:
|
||||
- C developers,
|
||||
- asm developers,
|
||||
- platform-specific developers,
|
||||
- GPGPU developers,
|
||||
- testers.
|
||||
|
||||
Our contributions guidelines are quite strict. We want to build a coherent codebase to simplify maintenance and achieve the highest possible speed.
|
||||
|
||||
Notably, the codebase is in pure C and asm.
|
||||
|
||||
We are on IRC, on the **#dav1d** channel on [*Libera.chat*](http://libera.chat/). If you do not have an IRC Client at hand, use [IRC Web Interface](https://web.libera.chat/#dav1d).
|
||||
|
||||
See the [contributions document](CONTRIBUTING.md).
|
||||
|
||||
## CLA
|
||||
|
||||
There is no CLA.
|
||||
|
||||
People will keep their copyright and their authorship rights, while adhering to the BSD 2-clause license.
|
||||
|
||||
VideoLAN will only have the collective work rights.
|
||||
|
||||
## CoC
|
||||
|
||||
The [VideoLAN Code of Conduct](https://wiki.videolan.org/CoC) applies to this project.
|
||||
|
||||
# Compile
|
||||
## General compilation steps
|
||||
|
||||
1. Install [Meson](https://mesonbuild.com/) (0.49 or higher), [Ninja](https://ninja-build.org/), and, for x86\* targets, [nasm](https://nasm.us/) (2.14 or higher)
|
||||
2. Run `mkdir build && cd build` to create a build directory and enter it
|
||||
3. Run `meson setup ..` to configure meson, add `--default-library=static` if static linking is desired
|
||||
4. Run `ninja` to compile
|
||||
|
||||
Following are modification of step 3 and 4, for specific purpose.
|
||||
|
||||
## Cross-Compilation for 32- or 64-bit Windows, 32-bit Linux
|
||||
|
||||
If you're on a linux build machine trying to compile .exe for a Windows target/host machine, configure meson like this
|
||||
|
||||
```
|
||||
meson setup .. --cross-file=../package/crossfiles/x86_64-w64-mingw32.meson
|
||||
```
|
||||
|
||||
or, for 32-bit:
|
||||
|
||||
```
|
||||
meson setup .. --cross-file=../package/crossfiles/i686-w64-mingw32.meson
|
||||
```
|
||||
|
||||
`mingw-w64` is a pre-requisite and should be installed on your linux machine via your preferred method or package manager. Note the binary name formats may differ between distributions. Verify the names, and use `alias` if certain binaries cannot be found.
|
||||
|
||||
For 32-bit linux, run
|
||||
|
||||
```
|
||||
meson setup .. --cross-file=../package/crossfiles/i686-linux32.meson
|
||||
```
|
||||
|
||||
## Build documentation
|
||||
|
||||
1. Make sure [doxygen](https://www.doxygen.nl/) and [graphviz](https://www.graphviz.org/) are installed.
|
||||
2. Run `meson setup .. -Denable_docs=true` to configure meson to generate docs from the build directory.
|
||||
3. Run `ninja doc/html` to build the docs
|
||||
|
||||
The result can be found in `build/doc/html/`. An online version built from master can be found [here](https://videolan.videolan.me/dav1d/).
|
||||
|
||||
# Run tests
|
||||
|
||||
1. In the root directory, run `git clone https://code.videolan.org/videolan/dav1d-test-data.git tests/dav1d-test-data` to fetch the test data repository
|
||||
2. During meson configuration, specify `-Dtestdata_tests=true`
|
||||
3. Run `meson test -v` after compiling
|
||||
|
||||
## Decoder conformance tests (optional but encouraged)
|
||||
|
||||
1. Download the argon conformance bitstreams from https://streams.videolan.org/argon/
|
||||
2. Extract into dav1d directory by running `tar -xvf argon.tar.zst`
|
||||
3. Execute tests with `tests/dav1d_argon.bash -d build/tools/dav1d -a argon`
|
||||
4. Expected outcome is `2763 files successfully verified in XXmYYs (dav1d 1.x.y-zz-gHHHHHHH filmgrain=1 cpumask=-1)`
|
||||
|
||||
# Support
|
||||
|
||||
This project is partially funded by the *Alliance for Open Media*/**AOM** and is supported by TwoOrioles and VideoLabs.
|
||||
|
||||
These companies can provide support and integration help, should you need it.
|
||||
|
||||
|
||||
# FAQ
|
||||
|
||||
## Why do you not improve libaom rather than starting a new project?
|
||||
|
||||
- We believe that libaom is a very good library. It was however developed for research purposes during AV1 design.
|
||||
We think that an implementation written from scratch can achieve faster decoding, in the same way that *ffvp9* was faster than *libvpx*.
|
||||
|
||||
## Is dav1d a recursive acronym?
|
||||
|
||||
- Yes.
|
||||
|
||||
## Can I help?
|
||||
|
||||
- Yes. See the [contributions document](CONTRIBUTING.md).
|
||||
|
||||
## I am not a developer. Can I help?
|
||||
|
||||
- Yes. We need testers, bug reporters and documentation writers.
|
||||
|
||||
## What about the AV1 patent license?
|
||||
|
||||
- This project is an implementation of a decoder. It gives you no special rights on the AV1 patents.
|
||||
|
||||
Please read the [AV1 patent license](doc/PATENTS) that applies to the AV1 specification and codec.
|
||||
|
||||
## Will you care about <my_arch>? <my_os>?
|
||||
|
||||
- We do, but we don't have either the time or the knowledge. Therefore, patches and contributions welcome.
|
||||
35
media/libdav1d/src/THANKS.md
Normal file
35
media/libdav1d/src/THANKS.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# The dav1d project and VideoLAN association would like to thank
|
||||
|
||||
## AOM
|
||||
The Alliance for Open Media (AOM) for partially funding this project.
|
||||
|
||||
## Companies
|
||||
* Two Orioles LLC, for important coding effort
|
||||
* VideoLabs SAS
|
||||
|
||||
## Projects
|
||||
* VideoLAN
|
||||
* FFmpeg
|
||||
* libplacebo
|
||||
|
||||
## Individual
|
||||
|
||||
And all the dav1d Authors (git shortlog -sn), including:
|
||||
|
||||
Henrik Gramner, Martin Storsjö, Ronald S. Bultje, Janne Grunau, James Almer,
|
||||
Victorien Le Couviour--Tuffet, Matthias Dressel, Nathan E. Egge,
|
||||
Jean-Baptiste Kempf, Marvin Scholz, Luc Trudeau, Niklas Haas,
|
||||
Hugo Beauzée-Luyssen, Konstantin Pavlov, David Michael Barr, Steve Lhomme,
|
||||
yuanhecai, Luca Barbato, Wan-Teh Chang, Kyle Siefring, B Krishnan Iyer,
|
||||
Francois Cartegnie, Liwei Wang, David Conrad, Derek Buitenhuis, Jan Beich,
|
||||
Michael Bradshaw, Raphaël Zumer, Xuefeng Jiang, Arpad Panyik, Christophe Gisquet,
|
||||
Justin Bull, Boyuan Xiao, Dale Curtis, Emmanuel Gil Peyrot, Raphael Zumer,
|
||||
Rupert Swarbrick, Thierry Foucu, Thomas Daede, jinbo, André Kempe, Colin Lee,
|
||||
Jonathan Wright, Lynne, Michail Alvanos, Nico Weber, Salome Thirot, SmilingWolf,
|
||||
Tristan Laurent, Tristan Matthews, Vittorio Giovara, Yannis Guyon,
|
||||
Andrey Semashev, Anisse Astier, Anton Mitrofanov, Charlie Hayden, Dmitriy Sychov,
|
||||
Ewout ter Hoeven, Fred Barbier, Hao Chen, Jean-Yves Avenard, Joe Drago,
|
||||
Mark Shuttleworth, Matthieu Bouron, Mehdi Sabwat, Nicolas Frattaroli,
|
||||
Pablo Stebler, Rostislav Pehlivanov, Sebastian Dröge, Shiz, Steinar Midtskogen,
|
||||
Sylvain BERTRAND, Sylvestre Ledru, Timo Gurr, Vibhoothi,
|
||||
Vignesh Venkatasubramanian, Xavier Claessens, Xu Guangxin, kossh1 and skal.
|
||||
23
media/libdav1d/src/doc/Doxyfile.in.in
Normal file
23
media/libdav1d/src/doc/Doxyfile.in.in
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
PROJECT_NAME = dav1d
|
||||
PROJECT_NUMBER = \@VCS_TAG\@
|
||||
PROJECT_BRIEF = dav1d is an AV1 decoder
|
||||
OUTPUT_DIRECTORY = @DOXYGEN_OUTPUT@
|
||||
STRIP_FROM_PATH = @DOXYGEN_STRIP@
|
||||
OUTPUT_LANGUAGE = English
|
||||
TAB_SIZE = 4
|
||||
EXTRACT_ALL = YES
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
TYPEDEF_HIDES_STRUCT = YES
|
||||
HAVE_DOT = YES
|
||||
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_AS_ERROR = FAIL_ON_WARNINGS
|
||||
|
||||
INPUT = @DOXYGEN_INPUT@
|
||||
FILE_PATTERNS = *.h
|
||||
|
||||
GENERATE_HTML = YES
|
||||
GENERATE_LATEX = NO
|
||||
108
media/libdav1d/src/doc/PATENTS
Normal file
108
media/libdav1d/src/doc/PATENTS
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
Alliance for Open Media Patent License 1.0
|
||||
|
||||
1. License Terms.
|
||||
|
||||
1.1. Patent License. Subject to the terms and conditions of this License, each
|
||||
Licensor, on behalf of itself and successors in interest and assigns,
|
||||
grants Licensee a non-sublicensable, perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as expressly stated in this
|
||||
License) patent license to its Necessary Claims to make, use, sell, offer
|
||||
for sale, import or distribute any Implementation.
|
||||
|
||||
1.2. Conditions.
|
||||
|
||||
1.2.1. Availability. As a condition to the grant of rights to Licensee to make,
|
||||
sell, offer for sale, import or distribute an Implementation under
|
||||
Section 1.1, Licensee must make its Necessary Claims available under
|
||||
this License, and must reproduce this License with any Implementation
|
||||
as follows:
|
||||
|
||||
a. For distribution in source code, by including this License in the
|
||||
root directory of the source code with its Implementation.
|
||||
|
||||
b. For distribution in any other form (including binary, object form,
|
||||
and/or hardware description code (e.g., HDL, RTL, Gate Level Netlist,
|
||||
GDSII, etc.)), by including this License in the documentation, legal
|
||||
notices, and/or other written materials provided with the
|
||||
Implementation.
|
||||
|
||||
1.2.2. Additional Conditions. This license is directly from Licensor to
|
||||
Licensee. Licensee acknowledges as a condition of benefiting from it
|
||||
that no rights from Licensor are received from suppliers, distributors,
|
||||
or otherwise in connection with this License.
|
||||
|
||||
1.3. Defensive Termination. If any Licensee, its Affiliates, or its agents
|
||||
initiates patent litigation or files, maintains, or voluntarily
|
||||
participates in a lawsuit against another entity or any person asserting
|
||||
that any Implementation infringes Necessary Claims, any patent licenses
|
||||
granted under this License directly to the Licensee are immediately
|
||||
terminated as of the date of the initiation of action unless 1) that suit
|
||||
was in response to a corresponding suit regarding an Implementation first
|
||||
brought against an initiating entity, or 2) that suit was brought to
|
||||
enforce the terms of this License (including intervention in a third-party
|
||||
action by a Licensee).
|
||||
|
||||
1.4. Disclaimers. The Reference Implementation and Specification are provided
|
||||
"AS IS" and without warranty. The entire risk as to implementing or
|
||||
otherwise using the Reference Implementation or Specification is assumed
|
||||
by the implementer and user. Licensor expressly disclaims any warranties
|
||||
(express, implied, or otherwise), including implied warranties of
|
||||
merchantability, non-infringement, fitness for a particular purpose, or
|
||||
title, related to the material. IN NO EVENT WILL LICENSOR BE LIABLE TO
|
||||
ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL,
|
||||
INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF
|
||||
ACTION OF ANY KIND WITH RESPECT TO THIS LICENSE, WHETHER BASED ON BREACH
|
||||
OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR
|
||||
NOT THE OTHER PARTRY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
2. Definitions.
|
||||
|
||||
2.1. Affiliate. “Affiliate” means an entity that directly or indirectly
|
||||
Controls, is Controlled by, or is under common Control of that party.
|
||||
|
||||
2.2. Control. “Control” means direct or indirect control of more than 50% of
|
||||
the voting power to elect directors of that corporation, or for any other
|
||||
entity, the power to direct management of such entity.
|
||||
|
||||
2.3. Decoder. "Decoder" means any decoder that conforms fully with all
|
||||
non-optional portions of the Specification.
|
||||
|
||||
2.4. Encoder. "Encoder" means any encoder that produces a bitstream that can
|
||||
be decoded by a Decoder only to the extent it produces such a bitstream.
|
||||
|
||||
2.5. Final Deliverable. “Final Deliverable” means the final version of a
|
||||
deliverable approved by the Alliance for Open Media as a Final
|
||||
Deliverable.
|
||||
|
||||
2.6. Implementation. "Implementation" means any implementation, including the
|
||||
Reference Implementation, that is an Encoder and/or a Decoder. An
|
||||
Implementation also includes components of an Implementation only to the
|
||||
extent they are used as part of an Implementation.
|
||||
|
||||
2.7. License. “License” means this license.
|
||||
|
||||
2.8. Licensee. “Licensee” means any person or entity who exercises patent
|
||||
rights granted under this License.
|
||||
|
||||
2.9. Licensor. "Licensor" means (i) any Licensee that makes, sells, offers
|
||||
for sale, imports or distributes any Implementation, or (ii) a person
|
||||
or entity that has a licensing obligation to the Implementation as a
|
||||
result of its membership and/or participation in the Alliance for Open
|
||||
Media working group that developed the Specification.
|
||||
|
||||
2.10. Necessary Claims. "Necessary Claims" means all claims of patents or
|
||||
patent applications, (a) that currently or at any time in the future,
|
||||
are owned or controlled by the Licensor, and (b) (i) would be an
|
||||
Essential Claim as defined by the W3C Policy as of February 5, 2004
|
||||
(https://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential)
|
||||
as if the Specification was a W3C Recommendation; or (ii) are infringed
|
||||
by the Reference Implementation.
|
||||
|
||||
2.11. Reference Implementation. “Reference Implementation” means an Encoder
|
||||
and/or Decoder released by the Alliance for Open Media as a Final
|
||||
Deliverable.
|
||||
|
||||
2.12. Specification. “Specification” means the specification designated by
|
||||
the Alliance for Open Media as a Final Deliverable for which this
|
||||
License was issued.
|
||||
|
||||
BIN
media/libdav1d/src/doc/dav1d_logo.png
Normal file
BIN
media/libdav1d/src/doc/dav1d_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
1
media/libdav1d/src/doc/dav1d_logo.svg
Normal file
1
media/libdav1d/src/doc/dav1d_logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.3 KiB |
51
media/libdav1d/src/doc/meson.build
Normal file
51
media/libdav1d/src/doc/meson.build
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Copyright © 2018-2022, VideoLAN and dav1d authors
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
if not get_option('enable_docs')
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
doxygen = find_program('doxygen')
|
||||
dot = find_program('dot')
|
||||
|
||||
conf_data = configuration_data()
|
||||
conf_data.set('DOXYGEN_INPUT', dav1d_src_root / 'include/dav1d')
|
||||
conf_data.set('DOXYGEN_STRIP', dav1d_src_root / 'include')
|
||||
conf_data.set('DOXYGEN_OUTPUT', meson.current_build_dir())
|
||||
doxyfile = configure_file(input: 'Doxyfile.in.in',
|
||||
output: 'Doxyfile.in',
|
||||
configuration: conf_data)
|
||||
|
||||
doxyfile_rev_target = vcs_tag(command: [
|
||||
'git', '--git-dir', dav1d_git_dir, 'describe', '--long', '--always'
|
||||
],
|
||||
input: doxyfile,
|
||||
output: 'Doxyfile'
|
||||
)
|
||||
|
||||
custom_target('doc',
|
||||
build_by_default: false,
|
||||
command: [doxygen, doxyfile_rev_target],
|
||||
output: ['html']
|
||||
)
|
||||
792
media/libdav1d/src/examples/dav1dplay.c
Normal file
792
media/libdav1d/src/examples/dav1dplay.c
Normal file
|
|
@ -0,0 +1,792 @@
|
|||
/*
|
||||
* Copyright © 2019, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "vcs_version.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "dav1d/dav1d.h"
|
||||
|
||||
#include "common/attributes.h"
|
||||
#include "tools/input/input.h"
|
||||
#include "dp_fifo.h"
|
||||
#include "dp_renderer.h"
|
||||
|
||||
#define FRAME_OFFSET_TO_PTS(foff) \
|
||||
(uint64_t)(((foff) * rd_ctx->spf) * 1000000000.0 + .5)
|
||||
#define TS_TO_PTS(ts) \
|
||||
(uint64_t)(((ts) * rd_ctx->timebase) * 1000000000.0 + .5)
|
||||
|
||||
// Selected renderer callbacks and cookie
|
||||
static const Dav1dPlayRenderInfo *renderer_info = { NULL };
|
||||
|
||||
/**
|
||||
* Render context structure
|
||||
* This structure contains informations necessary
|
||||
* to be shared between the decoder and the renderer
|
||||
* threads.
|
||||
*/
|
||||
typedef struct render_context
|
||||
{
|
||||
Dav1dPlaySettings settings;
|
||||
Dav1dSettings lib_settings;
|
||||
|
||||
// Renderer private data (passed to callbacks)
|
||||
void *rd_priv;
|
||||
|
||||
// Lock to protect access to the context structure
|
||||
SDL_mutex *lock;
|
||||
|
||||
// Timestamp of last displayed frame (in timebase unit)
|
||||
int64_t last_ts;
|
||||
// Timestamp of last decoded frame (in timebase unit)
|
||||
int64_t current_ts;
|
||||
// Ticks when last frame was received
|
||||
uint32_t last_ticks;
|
||||
// PTS time base
|
||||
double timebase;
|
||||
// Seconds per frame
|
||||
double spf;
|
||||
// Number of frames
|
||||
uint32_t total;
|
||||
|
||||
// Fifo
|
||||
Dav1dPlayPtrFifo *fifo;
|
||||
|
||||
// Custom SDL2 event types
|
||||
uint32_t event_types;
|
||||
|
||||
// User pause state
|
||||
uint8_t user_paused;
|
||||
// Internal pause state
|
||||
uint8_t paused;
|
||||
// Start of internal pause state
|
||||
uint32_t pause_start;
|
||||
// Duration of internal pause state
|
||||
uint32_t pause_time;
|
||||
|
||||
// Seek accumulator
|
||||
int seek;
|
||||
|
||||
// Indicates if termination of the decoder thread was requested
|
||||
uint8_t dec_should_terminate;
|
||||
} Dav1dPlayRenderContext;
|
||||
|
||||
static void dp_settings_print_usage(const char *const app,
|
||||
const char *const reason, ...)
|
||||
{
|
||||
if (reason) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, reason);
|
||||
vfprintf(stderr, reason, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n\n");
|
||||
}
|
||||
fprintf(stderr, "Usage: %s [options]\n\n", app);
|
||||
fprintf(stderr, "Supported options:\n"
|
||||
" --input/-i $file: input file\n"
|
||||
" --untimed/-u: ignore PTS, render as fast as possible\n"
|
||||
" --threads $num: number of threads (default: 0)\n"
|
||||
" --framedelay $num: maximum frame delay, capped at $threads (default: 0);\n"
|
||||
" set to 1 for low-latency decoding\n"
|
||||
" --highquality: enable high quality rendering\n"
|
||||
" --zerocopy/-z: enable zero copy upload path\n"
|
||||
" --gpugrain/-g: enable GPU grain synthesis\n"
|
||||
" --fullscreen/-f: enable full screen mode\n"
|
||||
" --version/-v: print version and exit\n"
|
||||
" --renderer/-r: select renderer backend (default: auto)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static unsigned parse_unsigned(const char *const optarg, const int option,
|
||||
const char *const app)
|
||||
{
|
||||
char *end;
|
||||
const unsigned res = (unsigned) strtoul(optarg, &end, 0);
|
||||
if (*end || end == optarg)
|
||||
dp_settings_print_usage(app, "Invalid argument \"%s\" for option %s; should be an integer",
|
||||
optarg, option);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void dp_rd_ctx_parse_args(Dav1dPlayRenderContext *rd_ctx,
|
||||
const int argc, char *const *const argv)
|
||||
{
|
||||
int o;
|
||||
Dav1dPlaySettings *settings = &rd_ctx->settings;
|
||||
Dav1dSettings *lib_settings = &rd_ctx->lib_settings;
|
||||
|
||||
// Short options
|
||||
static const char short_opts[] = "i:vuzgfr:";
|
||||
|
||||
enum {
|
||||
ARG_THREADS = 256,
|
||||
ARG_FRAME_DELAY,
|
||||
ARG_HIGH_QUALITY,
|
||||
};
|
||||
|
||||
// Long options
|
||||
static const struct option long_opts[] = {
|
||||
{ "input", 1, NULL, 'i' },
|
||||
{ "version", 0, NULL, 'v' },
|
||||
{ "untimed", 0, NULL, 'u' },
|
||||
{ "threads", 1, NULL, ARG_THREADS },
|
||||
{ "framedelay", 1, NULL, ARG_FRAME_DELAY },
|
||||
{ "highquality", 0, NULL, ARG_HIGH_QUALITY },
|
||||
{ "zerocopy", 0, NULL, 'z' },
|
||||
{ "gpugrain", 0, NULL, 'g' },
|
||||
{ "fullscreen", 0, NULL, 'f'},
|
||||
{ "renderer", 0, NULL, 'r'},
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
while ((o = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
|
||||
switch (o) {
|
||||
case 'i':
|
||||
settings->inputfile = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
fprintf(stderr, "%s\n", dav1d_version());
|
||||
exit(0);
|
||||
case 'u':
|
||||
settings->untimed = true;
|
||||
break;
|
||||
case ARG_HIGH_QUALITY:
|
||||
settings->highquality = true;
|
||||
break;
|
||||
case 'z':
|
||||
settings->zerocopy = true;
|
||||
break;
|
||||
case 'g':
|
||||
settings->gpugrain = true;
|
||||
break;
|
||||
case 'f':
|
||||
settings->fullscreen = true;
|
||||
break;
|
||||
case 'r':
|
||||
settings->renderer_name = optarg;
|
||||
break;
|
||||
case ARG_THREADS:
|
||||
lib_settings->n_threads =
|
||||
parse_unsigned(optarg, ARG_THREADS, argv[0]);
|
||||
break;
|
||||
case ARG_FRAME_DELAY:
|
||||
lib_settings->max_frame_delay =
|
||||
parse_unsigned(optarg, ARG_FRAME_DELAY, argv[0]);
|
||||
break;
|
||||
default:
|
||||
dp_settings_print_usage(argv[0], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
dp_settings_print_usage(argv[0],
|
||||
"Extra/unused arguments found, e.g. '%s'\n", argv[optind]);
|
||||
if (!settings->inputfile)
|
||||
dp_settings_print_usage(argv[0], "Input file (-i/--input) is required");
|
||||
if (settings->renderer_name && strcmp(settings->renderer_name, "auto") == 0)
|
||||
settings->renderer_name = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a Dav1dPlayRenderContext
|
||||
*/
|
||||
static void dp_rd_ctx_destroy(Dav1dPlayRenderContext *rd_ctx)
|
||||
{
|
||||
assert(rd_ctx != NULL);
|
||||
|
||||
renderer_info->destroy_renderer(rd_ctx->rd_priv);
|
||||
dp_fifo_destroy(rd_ctx->fifo);
|
||||
SDL_DestroyMutex(rd_ctx->lock);
|
||||
free(rd_ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Dav1dPlayRenderContext
|
||||
*
|
||||
* \note The Dav1dPlayRenderContext must be destroyed
|
||||
* again by using dp_rd_ctx_destroy.
|
||||
*/
|
||||
static Dav1dPlayRenderContext *dp_rd_ctx_create(int argc, char **argv)
|
||||
{
|
||||
Dav1dPlayRenderContext *rd_ctx;
|
||||
|
||||
// Alloc
|
||||
rd_ctx = calloc(1, sizeof(Dav1dPlayRenderContext));
|
||||
if (rd_ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Parse and validate arguments
|
||||
dav1d_default_settings(&rd_ctx->lib_settings);
|
||||
memset(&rd_ctx->settings, 0, sizeof(rd_ctx->settings));
|
||||
dp_rd_ctx_parse_args(rd_ctx, argc, argv);
|
||||
|
||||
// Init SDL2 library
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) {
|
||||
fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// Register a custom event to notify our SDL main thread
|
||||
// about new frames
|
||||
rd_ctx->event_types = SDL_RegisterEvents(3);
|
||||
if (rd_ctx->event_types == UINT32_MAX) {
|
||||
fprintf(stderr, "Failure to create custom SDL event types!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rd_ctx->fifo = dp_fifo_create(5);
|
||||
if (rd_ctx->fifo == NULL) {
|
||||
fprintf(stderr, "Failed to create FIFO for output pictures!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rd_ctx->lock = SDL_CreateMutex();
|
||||
if (rd_ctx->lock == NULL) {
|
||||
fprintf(stderr, "SDL_CreateMutex failed: %s\n", SDL_GetError());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// Select renderer
|
||||
renderer_info = dp_get_renderer(rd_ctx->settings.renderer_name);
|
||||
|
||||
if (renderer_info == NULL) {
|
||||
printf("No suitable renderer matching %s found.\n",
|
||||
(rd_ctx->settings.renderer_name) ? rd_ctx->settings.renderer_name : "auto");
|
||||
} else {
|
||||
printf("Using %s renderer\n", renderer_info->name);
|
||||
}
|
||||
|
||||
rd_ctx->rd_priv = (renderer_info) ? renderer_info->create_renderer(&rd_ctx->settings) : NULL;
|
||||
if (rd_ctx->rd_priv == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return rd_ctx;
|
||||
|
||||
fail:
|
||||
if (rd_ctx->lock)
|
||||
SDL_DestroyMutex(rd_ctx->lock);
|
||||
if (rd_ctx->fifo)
|
||||
dp_fifo_destroy(rd_ctx->fifo);
|
||||
free(rd_ctx);
|
||||
SDL_Quit();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify about new event
|
||||
*/
|
||||
static void dp_rd_ctx_post_event(Dav1dPlayRenderContext *rd_ctx, uint32_t type)
|
||||
{
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = type;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the decoder context with a new dav1d picture
|
||||
*
|
||||
* Once the decoder decoded a new picture, this call can be used
|
||||
* to update the internal texture of the render context with the
|
||||
* new picture.
|
||||
*/
|
||||
static void dp_rd_ctx_update_with_dav1d_picture(Dav1dPlayRenderContext *rd_ctx,
|
||||
Dav1dPicture *dav1d_pic)
|
||||
{
|
||||
rd_ctx->current_ts = dav1d_pic->m.timestamp;
|
||||
renderer_info->update_frame(rd_ctx->rd_priv, dav1d_pic, &rd_ctx->settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle pause state
|
||||
*/
|
||||
static void dp_rd_ctx_toggle_pause(Dav1dPlayRenderContext *rd_ctx)
|
||||
{
|
||||
SDL_LockMutex(rd_ctx->lock);
|
||||
rd_ctx->user_paused = !rd_ctx->user_paused;
|
||||
if (rd_ctx->seek)
|
||||
goto out;
|
||||
rd_ctx->paused = rd_ctx->user_paused;
|
||||
uint32_t now = SDL_GetTicks();
|
||||
if (rd_ctx->paused)
|
||||
rd_ctx->pause_start = now;
|
||||
else {
|
||||
rd_ctx->pause_time += now - rd_ctx->pause_start;
|
||||
rd_ctx->pause_start = 0;
|
||||
rd_ctx->last_ticks = now;
|
||||
}
|
||||
out:
|
||||
SDL_UnlockMutex(rd_ctx->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query pause state
|
||||
*/
|
||||
static int dp_rd_ctx_is_paused(Dav1dPlayRenderContext *rd_ctx)
|
||||
{
|
||||
int ret;
|
||||
SDL_LockMutex(rd_ctx->lock);
|
||||
ret = rd_ctx->paused;
|
||||
SDL_UnlockMutex(rd_ctx->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request seeking, in seconds
|
||||
*/
|
||||
static void dp_rd_ctx_seek(Dav1dPlayRenderContext *rd_ctx, int sec)
|
||||
{
|
||||
SDL_LockMutex(rd_ctx->lock);
|
||||
rd_ctx->seek += sec;
|
||||
if (!rd_ctx->paused)
|
||||
rd_ctx->pause_start = SDL_GetTicks();
|
||||
rd_ctx->paused = 1;
|
||||
SDL_UnlockMutex(rd_ctx->lock);
|
||||
}
|
||||
|
||||
static int decode_frame(Dav1dPicture **p, Dav1dContext *c,
|
||||
Dav1dData *data, DemuxerContext *in_ctx);
|
||||
static inline void destroy_pic(void *a);
|
||||
|
||||
/**
|
||||
* Seek the stream, if requested
|
||||
*/
|
||||
static int dp_rd_ctx_handle_seek(Dav1dPlayRenderContext *rd_ctx,
|
||||
DemuxerContext *in_ctx,
|
||||
Dav1dContext *c, Dav1dData *data)
|
||||
{
|
||||
int res = 0;
|
||||
SDL_LockMutex(rd_ctx->lock);
|
||||
if (!rd_ctx->seek)
|
||||
goto out;
|
||||
int64_t seek = rd_ctx->seek * 1000000000ULL;
|
||||
uint64_t pts = TS_TO_PTS(rd_ctx->current_ts);
|
||||
pts = ((int64_t)pts > -seek) ? pts + seek : 0;
|
||||
int end = pts >= FRAME_OFFSET_TO_PTS(rd_ctx->total);
|
||||
if (end)
|
||||
pts = FRAME_OFFSET_TO_PTS(rd_ctx->total - 1);
|
||||
uint64_t target_pts = pts;
|
||||
dav1d_flush(c);
|
||||
uint64_t shift = FRAME_OFFSET_TO_PTS(5);
|
||||
while (1) {
|
||||
if (shift > pts)
|
||||
shift = pts;
|
||||
if ((res = input_seek(in_ctx, pts - shift)))
|
||||
goto out;
|
||||
Dav1dSequenceHeader seq;
|
||||
uint64_t cur_pts;
|
||||
do {
|
||||
if ((res = input_read(in_ctx, data)))
|
||||
break;
|
||||
cur_pts = TS_TO_PTS(data->m.timestamp);
|
||||
res = dav1d_parse_sequence_header(&seq, data->data, data->sz);
|
||||
} while (res && cur_pts < pts);
|
||||
if (!res && cur_pts <= pts)
|
||||
break;
|
||||
if (shift > pts)
|
||||
shift = pts;
|
||||
pts -= shift;
|
||||
}
|
||||
if (!res) {
|
||||
pts = TS_TO_PTS(data->m.timestamp);
|
||||
while (pts < target_pts) {
|
||||
Dav1dPicture *p;
|
||||
if ((res = decode_frame(&p, c, data, in_ctx)))
|
||||
break;
|
||||
if (p) {
|
||||
pts = TS_TO_PTS(p->m.timestamp);
|
||||
if (pts < target_pts)
|
||||
destroy_pic(p);
|
||||
else {
|
||||
dp_fifo_push(rd_ctx->fifo, p);
|
||||
uint32_t type = rd_ctx->event_types + DAV1D_EVENT_SEEK_FRAME;
|
||||
dp_rd_ctx_post_event(rd_ctx, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
rd_ctx->last_ts = data->m.timestamp - rd_ctx->spf / rd_ctx->timebase;
|
||||
rd_ctx->current_ts = data->m.timestamp;
|
||||
}
|
||||
}
|
||||
out:
|
||||
rd_ctx->paused = rd_ctx->user_paused;
|
||||
if (!rd_ctx->paused && rd_ctx->seek) {
|
||||
uint32_t now = SDL_GetTicks();
|
||||
rd_ctx->pause_time += now - rd_ctx->pause_start;
|
||||
rd_ctx->pause_start = 0;
|
||||
rd_ctx->last_ticks = now;
|
||||
}
|
||||
rd_ctx->seek = 0;
|
||||
SDL_UnlockMutex(rd_ctx->lock);
|
||||
if (res)
|
||||
fprintf(stderr, "Error seeking, aborting\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate decoder thread (async)
|
||||
*/
|
||||
static void dp_rd_ctx_request_shutdown(Dav1dPlayRenderContext *rd_ctx)
|
||||
{
|
||||
SDL_LockMutex(rd_ctx->lock);
|
||||
rd_ctx->dec_should_terminate = 1;
|
||||
SDL_UnlockMutex(rd_ctx->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query state of decoder shutdown request
|
||||
*/
|
||||
static int dp_rd_ctx_should_terminate(Dav1dPlayRenderContext *rd_ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
SDL_LockMutex(rd_ctx->lock);
|
||||
ret = rd_ctx->dec_should_terminate;
|
||||
SDL_UnlockMutex(rd_ctx->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the currently available texture
|
||||
*
|
||||
* Renders the currently available texture, if any.
|
||||
*/
|
||||
static void dp_rd_ctx_render(Dav1dPlayRenderContext *rd_ctx)
|
||||
{
|
||||
SDL_LockMutex(rd_ctx->lock);
|
||||
// Calculate time since last frame was received
|
||||
uint32_t ticks_now = SDL_GetTicks();
|
||||
uint32_t ticks_diff = (rd_ctx->last_ticks != 0) ? ticks_now - rd_ctx->last_ticks : 0;
|
||||
|
||||
// Calculate when to display the frame
|
||||
int64_t ts_diff = rd_ctx->current_ts - rd_ctx->last_ts;
|
||||
int32_t pts_diff = (ts_diff * rd_ctx->timebase) * 1000.0 + .5;
|
||||
int32_t wait_time = pts_diff - ticks_diff;
|
||||
|
||||
// In untimed mode, simply don't wait
|
||||
if (rd_ctx->settings.untimed)
|
||||
wait_time = 0;
|
||||
|
||||
// This way of timing the playback is not accurate, as there is no guarantee
|
||||
// that SDL_Delay will wait for exactly the requested amount of time so in a
|
||||
// accurate player this would need to be done in a better way.
|
||||
if (wait_time > 0) {
|
||||
SDL_Delay(wait_time);
|
||||
} else if (wait_time < -10 && !rd_ctx->paused) { // Do not warn for minor time drifts
|
||||
fprintf(stderr, "Frame displayed %f seconds too late\n", wait_time / 1000.0);
|
||||
}
|
||||
|
||||
renderer_info->render(rd_ctx->rd_priv, &rd_ctx->settings);
|
||||
|
||||
rd_ctx->last_ts = rd_ctx->current_ts;
|
||||
rd_ctx->last_ticks = SDL_GetTicks();
|
||||
|
||||
SDL_UnlockMutex(rd_ctx->lock);
|
||||
}
|
||||
|
||||
static int decode_frame(Dav1dPicture **p, Dav1dContext *c,
|
||||
Dav1dData *data, DemuxerContext *in_ctx)
|
||||
{
|
||||
int res;
|
||||
// Send data packets we got from the demuxer to dav1d
|
||||
if ((res = dav1d_send_data(c, data)) < 0) {
|
||||
// On EAGAIN, dav1d can not consume more data and
|
||||
// dav1d_get_picture needs to be called first, which
|
||||
// will happen below, so just keep going in that case
|
||||
// and do not error out.
|
||||
if (res != DAV1D_ERR(EAGAIN)) {
|
||||
dav1d_data_unref(data);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
*p = calloc(1, sizeof(**p));
|
||||
// Try to get a decoded frame
|
||||
if ((res = dav1d_get_picture(c, *p)) < 0) {
|
||||
// In all error cases, even EAGAIN, p needs to be freed as
|
||||
// it is never added to the queue and would leak.
|
||||
free(*p);
|
||||
*p = NULL;
|
||||
// On EAGAIN, it means dav1d has not enough data to decode
|
||||
// therefore this is not a decoding error but just means
|
||||
// we need to feed it more data, which happens in the next
|
||||
// run of the decoder loop.
|
||||
if (res != DAV1D_ERR(EAGAIN))
|
||||
goto err;
|
||||
}
|
||||
return data->sz == 0 ? input_read(in_ctx, data) : 0;
|
||||
err:
|
||||
fprintf(stderr, "Error decoding frame: %s\n",
|
||||
strerror(-res));
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void destroy_pic(void *a)
|
||||
{
|
||||
Dav1dPicture *p = (Dav1dPicture *)a;
|
||||
dav1d_picture_unref(p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
/* Decoder thread "main" function */
|
||||
static int decoder_thread_main(void *cookie)
|
||||
{
|
||||
Dav1dPlayRenderContext *rd_ctx = cookie;
|
||||
|
||||
Dav1dPicture *p;
|
||||
Dav1dContext *c = NULL;
|
||||
Dav1dData data;
|
||||
DemuxerContext *in_ctx = NULL;
|
||||
int res = 0;
|
||||
unsigned total, timebase[2], fps[2];
|
||||
|
||||
Dav1dPlaySettings settings = rd_ctx->settings;
|
||||
|
||||
if ((res = input_open(&in_ctx, "ivf",
|
||||
settings.inputfile,
|
||||
fps, &total, timebase)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to open demuxer\n");
|
||||
res = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rd_ctx->timebase = (double)timebase[1] / timebase[0];
|
||||
rd_ctx->spf = (double)fps[1] / fps[0];
|
||||
rd_ctx->total = total;
|
||||
|
||||
if ((res = dav1d_open(&c, &rd_ctx->lib_settings))) {
|
||||
fprintf(stderr, "Failed opening dav1d decoder\n");
|
||||
res = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((res = input_read(in_ctx, &data)) < 0) {
|
||||
fprintf(stderr, "Failed demuxing input\n");
|
||||
res = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Decoder loop
|
||||
while (1) {
|
||||
if (dp_rd_ctx_should_terminate(rd_ctx) ||
|
||||
(res = dp_rd_ctx_handle_seek(rd_ctx, in_ctx, c, &data)) ||
|
||||
(res = decode_frame(&p, c, &data, in_ctx)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (p) {
|
||||
// Queue frame
|
||||
SDL_LockMutex(rd_ctx->lock);
|
||||
int seek = rd_ctx->seek;
|
||||
SDL_UnlockMutex(rd_ctx->lock);
|
||||
if (!seek) {
|
||||
dp_fifo_push(rd_ctx->fifo, p);
|
||||
uint32_t type = rd_ctx->event_types + DAV1D_EVENT_NEW_FRAME;
|
||||
dp_rd_ctx_post_event(rd_ctx, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Release remaining data
|
||||
if (data.sz > 0)
|
||||
dav1d_data_unref(&data);
|
||||
// Do not drain in case an error occured and caused us to leave the
|
||||
// decoding loop early.
|
||||
if (res < 0)
|
||||
goto cleanup;
|
||||
|
||||
// Drain decoder
|
||||
// When there is no more data to feed to the decoder, for example
|
||||
// because the file ended, we still need to request pictures, as
|
||||
// even though we do not have more data, there can be frames decoded
|
||||
// from data we sent before. So we need to call dav1d_get_picture until
|
||||
// we get an EAGAIN error.
|
||||
do {
|
||||
if (dp_rd_ctx_should_terminate(rd_ctx))
|
||||
break;
|
||||
p = calloc(1, sizeof(*p));
|
||||
res = dav1d_get_picture(c, p);
|
||||
if (res < 0) {
|
||||
free(p);
|
||||
if (res != DAV1D_ERR(EAGAIN)) {
|
||||
fprintf(stderr, "Error decoding frame: %s\n",
|
||||
strerror(-res));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Queue frame
|
||||
dp_fifo_push(rd_ctx->fifo, p);
|
||||
uint32_t type = rd_ctx->event_types + DAV1D_EVENT_NEW_FRAME;
|
||||
dp_rd_ctx_post_event(rd_ctx, type);
|
||||
}
|
||||
} while (res != DAV1D_ERR(EAGAIN));
|
||||
|
||||
cleanup:
|
||||
dp_rd_ctx_post_event(rd_ctx, rd_ctx->event_types + DAV1D_EVENT_DEC_QUIT);
|
||||
|
||||
if (in_ctx)
|
||||
input_close(in_ctx);
|
||||
if (c)
|
||||
dav1d_close(&c);
|
||||
|
||||
return (res != DAV1D_ERR(EAGAIN) && res < 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
SDL_Thread *decoder_thread;
|
||||
|
||||
// Check for version mismatch between library and tool
|
||||
const char *version = dav1d_version();
|
||||
if (strcmp(version, DAV1D_VERSION)) {
|
||||
fprintf(stderr, "Version mismatch (library: %s, executable: %s)\n",
|
||||
version, DAV1D_VERSION);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create render context
|
||||
Dav1dPlayRenderContext *rd_ctx = dp_rd_ctx_create(argc, argv);
|
||||
if (rd_ctx == NULL) {
|
||||
fprintf(stderr, "Failed creating render context\n");
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (rd_ctx->settings.zerocopy) {
|
||||
if (renderer_info->alloc_pic) {
|
||||
rd_ctx->lib_settings.allocator = (Dav1dPicAllocator) {
|
||||
.cookie = rd_ctx->rd_priv,
|
||||
.alloc_picture_callback = renderer_info->alloc_pic,
|
||||
.release_picture_callback = renderer_info->release_pic,
|
||||
};
|
||||
} else {
|
||||
fprintf(stderr, "--zerocopy unsupported by selected renderer\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (rd_ctx->settings.gpugrain) {
|
||||
if (renderer_info->supports_gpu_grain) {
|
||||
rd_ctx->lib_settings.apply_grain = 0;
|
||||
} else {
|
||||
fprintf(stderr, "--gpugrain unsupported by selected renderer\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Start decoder thread
|
||||
decoder_thread = SDL_CreateThread(decoder_thread_main, "Decoder thread", rd_ctx);
|
||||
|
||||
// Main loop
|
||||
#define NUM_MAX_EVENTS 8
|
||||
SDL_Event events[NUM_MAX_EVENTS];
|
||||
int num_frame_events = 0;
|
||||
uint32_t start_time = 0, n_out = 0;
|
||||
while (1) {
|
||||
int num_events = 0;
|
||||
SDL_WaitEvent(NULL);
|
||||
while (num_events < NUM_MAX_EVENTS && SDL_PollEvent(&events[num_events++]))
|
||||
break;
|
||||
for (int i = 0; i < num_events; ++i) {
|
||||
SDL_Event *e = &events[i];
|
||||
if (e->type == SDL_QUIT) {
|
||||
dp_rd_ctx_request_shutdown(rd_ctx);
|
||||
dp_fifo_flush(rd_ctx->fifo, destroy_pic);
|
||||
goto out;
|
||||
} else if (e->type == SDL_WINDOWEVENT) {
|
||||
if (e->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
// TODO: Handle window resizes
|
||||
} else if(e->window.event == SDL_WINDOWEVENT_EXPOSED) {
|
||||
dp_rd_ctx_render(rd_ctx);
|
||||
}
|
||||
} else if (e->type == SDL_KEYDOWN) {
|
||||
SDL_KeyboardEvent *kbde = (SDL_KeyboardEvent *)e;
|
||||
if (kbde->keysym.sym == SDLK_SPACE) {
|
||||
dp_rd_ctx_toggle_pause(rd_ctx);
|
||||
} else if (kbde->keysym.sym == SDLK_ESCAPE) {
|
||||
dp_rd_ctx_request_shutdown(rd_ctx);
|
||||
dp_fifo_flush(rd_ctx->fifo, destroy_pic);
|
||||
goto out;
|
||||
} else if (kbde->keysym.sym == SDLK_LEFT ||
|
||||
kbde->keysym.sym == SDLK_RIGHT)
|
||||
{
|
||||
if (kbde->keysym.sym == SDLK_LEFT)
|
||||
dp_rd_ctx_seek(rd_ctx, -5);
|
||||
else if (kbde->keysym.sym == SDLK_RIGHT)
|
||||
dp_rd_ctx_seek(rd_ctx, +5);
|
||||
dp_fifo_flush(rd_ctx->fifo, destroy_pic);
|
||||
SDL_FlushEvent(rd_ctx->event_types + DAV1D_EVENT_NEW_FRAME);
|
||||
num_frame_events = 0;
|
||||
}
|
||||
} else if (e->type == rd_ctx->event_types + DAV1D_EVENT_NEW_FRAME) {
|
||||
num_frame_events++;
|
||||
// Store current ticks for stats calculation
|
||||
if (start_time == 0)
|
||||
start_time = SDL_GetTicks();
|
||||
} else if (e->type == rd_ctx->event_types + DAV1D_EVENT_SEEK_FRAME) {
|
||||
// Dequeue frame and update the render context with it
|
||||
Dav1dPicture *p = dp_fifo_shift(rd_ctx->fifo);
|
||||
// Do not update textures during termination
|
||||
if (!dp_rd_ctx_should_terminate(rd_ctx)) {
|
||||
dp_rd_ctx_update_with_dav1d_picture(rd_ctx, p);
|
||||
n_out++;
|
||||
}
|
||||
destroy_pic(p);
|
||||
} else if (e->type == rd_ctx->event_types + DAV1D_EVENT_DEC_QUIT) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (num_frame_events && !dp_rd_ctx_is_paused(rd_ctx)) {
|
||||
// Dequeue frame and update the render context with it
|
||||
Dav1dPicture *p = dp_fifo_shift(rd_ctx->fifo);
|
||||
// Do not update textures during termination
|
||||
if (!dp_rd_ctx_should_terminate(rd_ctx)) {
|
||||
dp_rd_ctx_update_with_dav1d_picture(rd_ctx, p);
|
||||
dp_rd_ctx_render(rd_ctx);
|
||||
n_out++;
|
||||
}
|
||||
destroy_pic(p);
|
||||
num_frame_events--;
|
||||
}
|
||||
}
|
||||
|
||||
out:;
|
||||
// Print stats
|
||||
uint32_t time_ms = SDL_GetTicks() - start_time - rd_ctx->pause_time;
|
||||
printf("Decoded %u frames in %d seconds, avg %.02f fps\n",
|
||||
n_out, time_ms / 1000, n_out/ (time_ms / 1000.0));
|
||||
|
||||
int decoder_ret = 0;
|
||||
SDL_WaitThread(decoder_thread, &decoder_ret);
|
||||
dp_rd_ctx_destroy(rd_ctx);
|
||||
SDL_Quit();
|
||||
return decoder_ret;
|
||||
}
|
||||
147
media/libdav1d/src/examples/dp_fifo.c
Normal file
147
media/libdav1d/src/examples/dp_fifo.c
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright © 2019, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "dp_fifo.h"
|
||||
|
||||
// FIFO structure
|
||||
struct dp_fifo
|
||||
{
|
||||
SDL_mutex *lock;
|
||||
SDL_cond *cond_change;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
void **entries;
|
||||
int push_wait;
|
||||
int flush;
|
||||
};
|
||||
|
||||
|
||||
Dav1dPlayPtrFifo *dp_fifo_create(size_t capacity)
|
||||
{
|
||||
Dav1dPlayPtrFifo *fifo;
|
||||
|
||||
assert(capacity > 0);
|
||||
if (capacity <= 0)
|
||||
return NULL;
|
||||
|
||||
fifo = malloc(sizeof(*fifo));
|
||||
if (fifo == NULL)
|
||||
return NULL;
|
||||
|
||||
fifo->capacity = capacity;
|
||||
fifo->count = 0;
|
||||
fifo->push_wait = 0;
|
||||
fifo->flush = 0;
|
||||
|
||||
fifo->lock = SDL_CreateMutex();
|
||||
if (fifo->lock == NULL) {
|
||||
free(fifo);
|
||||
return NULL;
|
||||
}
|
||||
fifo->cond_change = SDL_CreateCond();
|
||||
if (fifo->cond_change == NULL) {
|
||||
SDL_DestroyMutex(fifo->lock);
|
||||
free(fifo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fifo->entries = calloc(capacity, sizeof(void*));
|
||||
if (fifo->entries == NULL) {
|
||||
dp_fifo_destroy(fifo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fifo;
|
||||
}
|
||||
|
||||
// Destroy FIFO
|
||||
void dp_fifo_destroy(Dav1dPlayPtrFifo *fifo)
|
||||
{
|
||||
assert(fifo->count == 0);
|
||||
SDL_DestroyMutex(fifo->lock);
|
||||
SDL_DestroyCond(fifo->cond_change);
|
||||
free(fifo->entries);
|
||||
free(fifo);
|
||||
}
|
||||
|
||||
// Push to FIFO
|
||||
void dp_fifo_push(Dav1dPlayPtrFifo *fifo, void *element)
|
||||
{
|
||||
SDL_LockMutex(fifo->lock);
|
||||
while (fifo->count == fifo->capacity) {
|
||||
fifo->push_wait = 1;
|
||||
SDL_CondWait(fifo->cond_change, fifo->lock);
|
||||
fifo->push_wait = 0;
|
||||
if (fifo->flush) {
|
||||
SDL_CondSignal(fifo->cond_change);
|
||||
SDL_UnlockMutex(fifo->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fifo->entries[fifo->count++] = element;
|
||||
if (fifo->count == 1)
|
||||
SDL_CondSignal(fifo->cond_change);
|
||||
SDL_UnlockMutex(fifo->lock);
|
||||
}
|
||||
|
||||
// Helper that shifts the FIFO array
|
||||
static void *dp_fifo_array_shift(void **arr, size_t len)
|
||||
{
|
||||
void *shifted_element = arr[0];
|
||||
for (size_t i = 1; i < len; ++i)
|
||||
arr[i-1] = arr[i];
|
||||
return shifted_element;
|
||||
}
|
||||
|
||||
// Get item from FIFO
|
||||
void *dp_fifo_shift(Dav1dPlayPtrFifo *fifo)
|
||||
{
|
||||
SDL_LockMutex(fifo->lock);
|
||||
while (fifo->count == 0)
|
||||
SDL_CondWait(fifo->cond_change, fifo->lock);
|
||||
void *res = dp_fifo_array_shift(fifo->entries, fifo->count--);
|
||||
if (fifo->count == fifo->capacity - 1)
|
||||
SDL_CondSignal(fifo->cond_change);
|
||||
SDL_UnlockMutex(fifo->lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
void dp_fifo_flush(Dav1dPlayPtrFifo *fifo, void (*destroy_elem)(void *))
|
||||
{
|
||||
SDL_LockMutex(fifo->lock);
|
||||
fifo->flush = 1;
|
||||
if (fifo->push_wait) {
|
||||
SDL_CondSignal(fifo->cond_change);
|
||||
SDL_CondWait(fifo->cond_change, fifo->lock);
|
||||
}
|
||||
while (fifo->count)
|
||||
destroy_elem(fifo->entries[--fifo->count]);
|
||||
fifo->flush = 0;
|
||||
SDL_UnlockMutex(fifo->lock);
|
||||
}
|
||||
63
media/libdav1d/src/examples/dp_fifo.h
Normal file
63
media/libdav1d/src/examples/dp_fifo.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright © 2019, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dav1dPlay FIFO helper
|
||||
*/
|
||||
|
||||
typedef struct dp_fifo Dav1dPlayPtrFifo;
|
||||
|
||||
/* Create a FIFO
|
||||
*
|
||||
* Creates a FIFO with the given capacity.
|
||||
* If the capacity is reached, new inserts into the FIFO
|
||||
* will block until enough space is available again.
|
||||
*/
|
||||
Dav1dPlayPtrFifo *dp_fifo_create(size_t capacity);
|
||||
|
||||
/* Destroy a FIFO
|
||||
*
|
||||
* The FIFO must be empty before it is destroyed!
|
||||
*/
|
||||
void dp_fifo_destroy(Dav1dPlayPtrFifo *fifo);
|
||||
|
||||
/* Shift FIFO
|
||||
*
|
||||
* Return the first item from the FIFO, thereby removing it from
|
||||
* the FIFO and making room for new entries.
|
||||
*/
|
||||
void *dp_fifo_shift(Dav1dPlayPtrFifo *fifo);
|
||||
|
||||
/* Push to FIFO
|
||||
*
|
||||
* Add an item to the end of the FIFO.
|
||||
* If the FIFO is full, this call will block until there is again enough
|
||||
* space in the FIFO, so calling this from the "consumer" thread if no
|
||||
* other thread will call dp_fifo_shift will lead to a deadlock.
|
||||
*/
|
||||
void dp_fifo_push(Dav1dPlayPtrFifo *fifo, void *element);
|
||||
|
||||
void dp_fifo_flush(Dav1dPlayPtrFifo *fifo, void (*destroy_elem)(void *));
|
||||
149
media/libdav1d/src/examples/dp_renderer.h
Normal file
149
media/libdav1d/src/examples/dp_renderer.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright © 2020, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dav1d/dav1d.h"
|
||||
|
||||
#include <SDL.h>
|
||||
#if HAVE_PLACEBO
|
||||
# include <libplacebo/config.h>
|
||||
#endif
|
||||
|
||||
// Check libplacebo Vulkan rendering
|
||||
#if HAVE_VULKAN && defined(SDL_VIDEO_VULKAN)
|
||||
# if defined(PL_HAVE_VULKAN) && PL_HAVE_VULKAN
|
||||
# define HAVE_RENDERER_PLACEBO 1
|
||||
# define HAVE_PLACEBO_VULKAN 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Check libplacebo OpenGL rendering
|
||||
#if defined(PL_HAVE_OPENGL) && PL_HAVE_OPENGL
|
||||
# define HAVE_RENDERER_PLACEBO 1
|
||||
# define HAVE_PLACEBO_OPENGL 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RENDERER_PLACEBO
|
||||
#define HAVE_RENDERER_PLACEBO 0
|
||||
#endif
|
||||
#ifndef HAVE_PLACEBO_VULKAN
|
||||
#define HAVE_PLACEBO_VULKAN 0
|
||||
#endif
|
||||
#ifndef HAVE_PLACEBO_OPENGL
|
||||
#define HAVE_PLACEBO_OPENGL 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Settings structure
|
||||
* Hold all settings available for the player,
|
||||
* this is usually filled by parsing arguments
|
||||
* from the console.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *inputfile;
|
||||
const char *renderer_name;
|
||||
int highquality;
|
||||
int untimed;
|
||||
int zerocopy;
|
||||
int gpugrain;
|
||||
int fullscreen;
|
||||
} Dav1dPlaySettings;
|
||||
|
||||
#define WINDOW_WIDTH 910
|
||||
#define WINDOW_HEIGHT 512
|
||||
|
||||
enum {
|
||||
DAV1D_EVENT_NEW_FRAME,
|
||||
DAV1D_EVENT_SEEK_FRAME,
|
||||
DAV1D_EVENT_DEC_QUIT
|
||||
};
|
||||
|
||||
/**
|
||||
* Renderer info
|
||||
*/
|
||||
typedef struct rdr_info
|
||||
{
|
||||
// Renderer name
|
||||
const char *name;
|
||||
// Cookie passed to the renderer implementation callbacks
|
||||
void *cookie;
|
||||
// Callback to create the renderer
|
||||
void* (*create_renderer)(const Dav1dPlaySettings *settings);
|
||||
// Callback to destroy the renderer
|
||||
void (*destroy_renderer)(void *cookie);
|
||||
// Callback to the render function that renders a prevously sent frame
|
||||
void (*render)(void *cookie, const Dav1dPlaySettings *settings);
|
||||
// Callback to the send frame function, _may_ also unref dav1d_pic!
|
||||
int (*update_frame)(void *cookie, Dav1dPicture *dav1d_pic,
|
||||
const Dav1dPlaySettings *settings);
|
||||
// Callback for alloc/release pictures (optional)
|
||||
int (*alloc_pic)(Dav1dPicture *pic, void *cookie);
|
||||
void (*release_pic)(Dav1dPicture *pic, void *cookie);
|
||||
// Whether or not this renderer can apply on-GPU film grain synthesis
|
||||
int supports_gpu_grain;
|
||||
} Dav1dPlayRenderInfo;
|
||||
|
||||
extern const Dav1dPlayRenderInfo rdr_placebo_vk;
|
||||
extern const Dav1dPlayRenderInfo rdr_placebo_gl;
|
||||
extern const Dav1dPlayRenderInfo rdr_sdl;
|
||||
|
||||
// Available renderes ordered by priority
|
||||
static const Dav1dPlayRenderInfo* const dp_renderers[] = {
|
||||
&rdr_placebo_vk,
|
||||
&rdr_placebo_gl,
|
||||
&rdr_sdl,
|
||||
};
|
||||
|
||||
static inline const Dav1dPlayRenderInfo *dp_get_renderer(const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < (sizeof(dp_renderers)/sizeof(*dp_renderers)); ++i)
|
||||
{
|
||||
if (dp_renderers[i]->name == NULL)
|
||||
continue;
|
||||
|
||||
if (name == NULL || strcmp(name, dp_renderers[i]->name) == 0) {
|
||||
return dp_renderers[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline SDL_Window *dp_create_sdl_window(int window_flags)
|
||||
{
|
||||
SDL_Window *win;
|
||||
window_flags |= SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
|
||||
win = SDL_CreateWindow("Dav1dPlay", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
WINDOW_WIDTH, WINDOW_HEIGHT, window_flags);
|
||||
if (!win)
|
||||
return NULL;
|
||||
|
||||
SDL_SetWindowResizable(win, SDL_TRUE);
|
||||
|
||||
return win;
|
||||
}
|
||||
437
media/libdav1d/src/examples/dp_renderer_placebo.c
Normal file
437
media/libdav1d/src/examples/dp_renderer_placebo.c
Normal file
|
|
@ -0,0 +1,437 @@
|
|||
/*
|
||||
* Copyright © 2020, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "dp_renderer.h"
|
||||
|
||||
#if HAVE_RENDERER_PLACEBO
|
||||
#include <assert.h>
|
||||
|
||||
#include <libplacebo/renderer.h>
|
||||
#include <libplacebo/utils/dav1d.h>
|
||||
|
||||
#if HAVE_PLACEBO_VULKAN
|
||||
# include <libplacebo/vulkan.h>
|
||||
# include <SDL_vulkan.h>
|
||||
#endif
|
||||
#if HAVE_PLACEBO_OPENGL
|
||||
# include <libplacebo/opengl.h>
|
||||
# include <SDL_opengl.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Renderer context for libplacebo
|
||||
*/
|
||||
typedef struct renderer_priv_ctx
|
||||
{
|
||||
// SDL window
|
||||
SDL_Window *win;
|
||||
// Placebo log
|
||||
pl_log log;
|
||||
// Placebo renderer
|
||||
pl_renderer renderer;
|
||||
#if HAVE_PLACEBO_VULKAN
|
||||
// Placebo Vulkan handle
|
||||
pl_vulkan vk;
|
||||
// Placebo Vulkan instance
|
||||
pl_vk_inst vk_inst;
|
||||
// Vulkan surface
|
||||
VkSurfaceKHR surf;
|
||||
#endif
|
||||
#if HAVE_PLACEBO_OPENGL
|
||||
// Placebo OpenGL handle
|
||||
pl_opengl gl;
|
||||
// SDL OpenGL context
|
||||
SDL_GLContext gl_context;
|
||||
#endif
|
||||
// Placebo GPU
|
||||
pl_gpu gpu;
|
||||
// Placebo swapchain
|
||||
pl_swapchain swapchain;
|
||||
// Lock protecting access to the texture
|
||||
SDL_mutex *lock;
|
||||
// Image to render, and planes backing them
|
||||
struct pl_frame image;
|
||||
pl_tex plane_tex[3];
|
||||
} Dav1dPlayRendererPrivateContext;
|
||||
|
||||
static Dav1dPlayRendererPrivateContext*
|
||||
placebo_renderer_create_common(const Dav1dPlaySettings *settings, int window_flags)
|
||||
{
|
||||
if (settings->fullscreen)
|
||||
window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
// Create Window
|
||||
SDL_Window *sdlwin = dp_create_sdl_window(window_flags | SDL_WINDOW_RESIZABLE);
|
||||
if (sdlwin == NULL) {
|
||||
fprintf(stderr, "Creating SDL window failed: %s\n", SDL_GetError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_ShowCursor(0);
|
||||
|
||||
// Alloc
|
||||
Dav1dPlayRendererPrivateContext *const rd_priv_ctx =
|
||||
calloc(1, sizeof(Dav1dPlayRendererPrivateContext));
|
||||
if (rd_priv_ctx == NULL) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
return NULL;
|
||||
}
|
||||
rd_priv_ctx->win = sdlwin;
|
||||
|
||||
// Init libplacebo
|
||||
rd_priv_ctx->log = pl_log_create(PL_API_VER, pl_log_params(
|
||||
.log_cb = pl_log_color,
|
||||
#ifndef NDEBUG
|
||||
.log_level = PL_LOG_DEBUG,
|
||||
#else
|
||||
.log_level = PL_LOG_WARN,
|
||||
#endif
|
||||
));
|
||||
if (rd_priv_ctx->log == NULL) {
|
||||
fprintf(stderr, "pl_log_create failed!\n");
|
||||
free(rd_priv_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create Mutex
|
||||
rd_priv_ctx->lock = SDL_CreateMutex();
|
||||
if (rd_priv_ctx->lock == NULL) {
|
||||
fprintf(stderr, "SDL_CreateMutex failed: %s\n", SDL_GetError());
|
||||
pl_log_destroy(&rd_priv_ctx->log);
|
||||
free(rd_priv_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rd_priv_ctx;
|
||||
}
|
||||
|
||||
#if HAVE_PLACEBO_OPENGL
|
||||
static void *placebo_renderer_create_gl(const Dav1dPlaySettings *settings)
|
||||
{
|
||||
SDL_Window *sdlwin = NULL;
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
|
||||
// Common init
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx =
|
||||
placebo_renderer_create_common(settings, SDL_WINDOW_OPENGL);
|
||||
|
||||
if (rd_priv_ctx == NULL)
|
||||
return NULL;
|
||||
sdlwin = rd_priv_ctx->win;
|
||||
|
||||
rd_priv_ctx->gl_context = SDL_GL_CreateContext(sdlwin);
|
||||
if (!rd_priv_ctx->gl_context) {
|
||||
fprintf(stderr, "Failed creating opengl context: %s\n", SDL_GetError());
|
||||
exit(2);
|
||||
}
|
||||
SDL_GL_MakeCurrent(sdlwin, rd_priv_ctx->gl_context);
|
||||
|
||||
rd_priv_ctx->gl = pl_opengl_create(rd_priv_ctx->log, pl_opengl_params(
|
||||
.allow_software = true,
|
||||
#ifndef NDEBUG
|
||||
.debug = true,
|
||||
#endif
|
||||
));
|
||||
if (!rd_priv_ctx->gl) {
|
||||
fprintf(stderr, "Failed creating opengl device!\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
rd_priv_ctx->swapchain = pl_opengl_create_swapchain(rd_priv_ctx->gl,
|
||||
pl_opengl_swapchain_params(
|
||||
.swap_buffers = (void (*)(void *)) SDL_GL_SwapWindow,
|
||||
.priv = sdlwin,
|
||||
));
|
||||
|
||||
if (!rd_priv_ctx->swapchain) {
|
||||
fprintf(stderr, "Failed creating opengl swapchain!\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int w = WINDOW_WIDTH, h = WINDOW_HEIGHT;
|
||||
SDL_GL_GetDrawableSize(sdlwin, &w, &h);
|
||||
|
||||
if (!pl_swapchain_resize(rd_priv_ctx->swapchain, &w, &h)) {
|
||||
fprintf(stderr, "Failed resizing vulkan swapchain!\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
rd_priv_ctx->gpu = rd_priv_ctx->gl->gpu;
|
||||
|
||||
if (w != WINDOW_WIDTH || h != WINDOW_HEIGHT)
|
||||
printf("Note: window dimensions differ (got %dx%d)\n", w, h);
|
||||
|
||||
return rd_priv_ctx;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_PLACEBO_VULKAN
|
||||
static void *placebo_renderer_create_vk(const Dav1dPlaySettings *settings)
|
||||
{
|
||||
SDL_Window *sdlwin = NULL;
|
||||
|
||||
// Common init
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx =
|
||||
placebo_renderer_create_common(settings, SDL_WINDOW_VULKAN);
|
||||
|
||||
if (rd_priv_ctx == NULL)
|
||||
return NULL;
|
||||
sdlwin = rd_priv_ctx->win;
|
||||
|
||||
// Init Vulkan
|
||||
unsigned num = 0;
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(sdlwin, &num, NULL)) {
|
||||
fprintf(stderr, "Failed enumerating Vulkan extensions: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char **extensions = malloc(num * sizeof(const char *));
|
||||
assert(extensions);
|
||||
|
||||
SDL_bool ok = SDL_Vulkan_GetInstanceExtensions(sdlwin, &num, extensions);
|
||||
if (!ok) {
|
||||
fprintf(stderr, "Failed getting Vk instance extensions\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (num > 0) {
|
||||
printf("Requesting %d additional Vulkan extensions:\n", num);
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
printf(" %s\n", extensions[i]);
|
||||
}
|
||||
|
||||
rd_priv_ctx->vk_inst = pl_vk_inst_create(rd_priv_ctx->log, pl_vk_inst_params(
|
||||
.extensions = extensions,
|
||||
.num_extensions = num,
|
||||
));
|
||||
if (!rd_priv_ctx->vk_inst) {
|
||||
fprintf(stderr, "Failed creating Vulkan instance!\n");
|
||||
exit(1);
|
||||
}
|
||||
free(extensions);
|
||||
|
||||
if (!SDL_Vulkan_CreateSurface(sdlwin, rd_priv_ctx->vk_inst->instance, &rd_priv_ctx->surf)) {
|
||||
fprintf(stderr, "Failed creating vulkan surface: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rd_priv_ctx->vk = pl_vulkan_create(rd_priv_ctx->log, pl_vulkan_params(
|
||||
.instance = rd_priv_ctx->vk_inst->instance,
|
||||
.surface = rd_priv_ctx->surf,
|
||||
.allow_software = true,
|
||||
));
|
||||
if (!rd_priv_ctx->vk) {
|
||||
fprintf(stderr, "Failed creating vulkan device!\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
// Create swapchain
|
||||
rd_priv_ctx->swapchain = pl_vulkan_create_swapchain(rd_priv_ctx->vk,
|
||||
pl_vulkan_swapchain_params(
|
||||
.surface = rd_priv_ctx->surf,
|
||||
.present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR,
|
||||
));
|
||||
|
||||
if (!rd_priv_ctx->swapchain) {
|
||||
fprintf(stderr, "Failed creating vulkan swapchain!\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int w = WINDOW_WIDTH, h = WINDOW_HEIGHT;
|
||||
if (!pl_swapchain_resize(rd_priv_ctx->swapchain, &w, &h)) {
|
||||
fprintf(stderr, "Failed resizing vulkan swapchain!\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
rd_priv_ctx->gpu = rd_priv_ctx->vk->gpu;
|
||||
|
||||
if (w != WINDOW_WIDTH || h != WINDOW_HEIGHT)
|
||||
printf("Note: window dimensions differ (got %dx%d)\n", w, h);
|
||||
|
||||
return rd_priv_ctx;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void placebo_renderer_destroy(void *cookie)
|
||||
{
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
|
||||
assert(rd_priv_ctx != NULL);
|
||||
|
||||
pl_renderer_destroy(&(rd_priv_ctx->renderer));
|
||||
pl_swapchain_destroy(&(rd_priv_ctx->swapchain));
|
||||
for (int i = 0; i < 3; i++)
|
||||
pl_tex_destroy(rd_priv_ctx->gpu, &(rd_priv_ctx->plane_tex[i]));
|
||||
|
||||
#if HAVE_PLACEBO_VULKAN
|
||||
if (rd_priv_ctx->vk) {
|
||||
pl_vulkan_destroy(&(rd_priv_ctx->vk));
|
||||
vkDestroySurfaceKHR(rd_priv_ctx->vk_inst->instance, rd_priv_ctx->surf, NULL);
|
||||
pl_vk_inst_destroy(&(rd_priv_ctx->vk_inst));
|
||||
}
|
||||
#endif
|
||||
#if HAVE_PLACEBO_OPENGL
|
||||
if (rd_priv_ctx->gl)
|
||||
pl_opengl_destroy(&(rd_priv_ctx->gl));
|
||||
if (rd_priv_ctx->gl_context)
|
||||
SDL_GL_DeleteContext(rd_priv_ctx->gl_context);
|
||||
#endif
|
||||
|
||||
SDL_DestroyWindow(rd_priv_ctx->win);
|
||||
|
||||
pl_log_destroy(&rd_priv_ctx->log);
|
||||
}
|
||||
|
||||
static void placebo_render(void *cookie, const Dav1dPlaySettings *settings)
|
||||
{
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
|
||||
assert(rd_priv_ctx != NULL);
|
||||
|
||||
SDL_LockMutex(rd_priv_ctx->lock);
|
||||
if (!rd_priv_ctx->image.num_planes) {
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare rendering
|
||||
if (rd_priv_ctx->renderer == NULL) {
|
||||
rd_priv_ctx->renderer = pl_renderer_create(rd_priv_ctx->log, rd_priv_ctx->gpu);
|
||||
}
|
||||
|
||||
struct pl_swapchain_frame frame;
|
||||
bool ok = pl_swapchain_start_frame(rd_priv_ctx->swapchain, &frame);
|
||||
if (!ok) {
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
struct pl_frame target;
|
||||
pl_frame_from_swapchain(&target, &frame);
|
||||
pl_rect2df_aspect_copy(&target.crop, &rd_priv_ctx->image.crop, 0.0);
|
||||
if (pl_frame_is_cropped(&target))
|
||||
pl_tex_clear(rd_priv_ctx->gpu, frame.fbo, (float[4]){ 0.0 });
|
||||
|
||||
if (!pl_render_image(rd_priv_ctx->renderer, &rd_priv_ctx->image, &target,
|
||||
settings->highquality ? &pl_render_default_params
|
||||
: &pl_render_fast_params))
|
||||
{
|
||||
fprintf(stderr, "Failed rendering frame!\n");
|
||||
pl_tex_clear(rd_priv_ctx->gpu, frame.fbo, (float[4]){ 1.0 });
|
||||
}
|
||||
|
||||
ok = pl_swapchain_submit_frame(rd_priv_ctx->swapchain);
|
||||
if (!ok) {
|
||||
fprintf(stderr, "Failed submitting frame!\n");
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
pl_swapchain_swap_buffers(rd_priv_ctx->swapchain);
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
}
|
||||
|
||||
static int placebo_upload_image(void *cookie, Dav1dPicture *dav1d_pic,
|
||||
const Dav1dPlaySettings *settings)
|
||||
{
|
||||
Dav1dPlayRendererPrivateContext *p = cookie;
|
||||
assert(p != NULL);
|
||||
int ret = 0;
|
||||
|
||||
if (!dav1d_pic)
|
||||
return ret;
|
||||
|
||||
SDL_LockMutex(p->lock);
|
||||
if (!pl_upload_dav1dpicture(p->gpu, &p->image, p->plane_tex, pl_dav1d_upload_params(
|
||||
.picture = dav1d_pic,
|
||||
.film_grain = settings->gpugrain,
|
||||
.gpu_allocated = settings->zerocopy,
|
||||
.asynchronous = true,
|
||||
)))
|
||||
{
|
||||
fprintf(stderr, "Failed uploading planes!\n");
|
||||
p->image = (struct pl_frame) {0};
|
||||
ret = -1;
|
||||
}
|
||||
SDL_UnlockMutex(p->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int placebo_alloc_pic(Dav1dPicture *const pic, void *cookie)
|
||||
{
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
|
||||
assert(rd_priv_ctx != NULL);
|
||||
|
||||
SDL_LockMutex(rd_priv_ctx->lock);
|
||||
int ret = pl_allocate_dav1dpicture(pic, (void *) rd_priv_ctx->gpu);
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void placebo_release_pic(Dav1dPicture *pic, void *cookie)
|
||||
{
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
|
||||
assert(rd_priv_ctx != NULL);
|
||||
|
||||
SDL_LockMutex(rd_priv_ctx->lock);
|
||||
pl_release_dav1dpicture(pic, (void *) rd_priv_ctx->gpu);
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
}
|
||||
|
||||
#if HAVE_PLACEBO_VULKAN
|
||||
const Dav1dPlayRenderInfo rdr_placebo_vk = {
|
||||
.name = "placebo-vk",
|
||||
.create_renderer = placebo_renderer_create_vk,
|
||||
.destroy_renderer = placebo_renderer_destroy,
|
||||
.render = placebo_render,
|
||||
.update_frame = placebo_upload_image,
|
||||
.alloc_pic = placebo_alloc_pic,
|
||||
.release_pic = placebo_release_pic,
|
||||
.supports_gpu_grain = 1,
|
||||
};
|
||||
#else
|
||||
const Dav1dPlayRenderInfo rdr_placebo_vk = { NULL };
|
||||
#endif
|
||||
|
||||
#if HAVE_PLACEBO_OPENGL
|
||||
const Dav1dPlayRenderInfo rdr_placebo_gl = {
|
||||
.name = "placebo-gl",
|
||||
.create_renderer = placebo_renderer_create_gl,
|
||||
.destroy_renderer = placebo_renderer_destroy,
|
||||
.render = placebo_render,
|
||||
.update_frame = placebo_upload_image,
|
||||
.supports_gpu_grain = 1,
|
||||
};
|
||||
#else
|
||||
const Dav1dPlayRenderInfo rdr_placebo_gl = { NULL };
|
||||
#endif
|
||||
|
||||
#else
|
||||
const Dav1dPlayRenderInfo rdr_placebo_vk = { NULL };
|
||||
const Dav1dPlayRenderInfo rdr_placebo_gl = { NULL };
|
||||
#endif
|
||||
175
media/libdav1d/src/examples/dp_renderer_sdl.c
Normal file
175
media/libdav1d/src/examples/dp_renderer_sdl.c
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Copyright © 2020, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "dp_renderer.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* Renderer context for SDL
|
||||
*/
|
||||
typedef struct renderer_priv_ctx
|
||||
{
|
||||
// SDL window
|
||||
SDL_Window *win;
|
||||
// SDL renderer
|
||||
SDL_Renderer *renderer;
|
||||
// Lock protecting access to the texture
|
||||
SDL_mutex *lock;
|
||||
// Texture to render
|
||||
SDL_Texture *tex;
|
||||
} Dav1dPlayRendererPrivateContext;
|
||||
|
||||
static void *sdl_renderer_create(const Dav1dPlaySettings *settings)
|
||||
{
|
||||
int window_flags = 0;
|
||||
if (settings->fullscreen)
|
||||
window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
SDL_Window *win = dp_create_sdl_window(window_flags);
|
||||
if (win == NULL) {
|
||||
fprintf(stderr, "Creating SDL window failed: %s\n", SDL_GetError());
|
||||
return NULL;
|
||||
}
|
||||
SDL_ShowCursor(0);
|
||||
|
||||
// Alloc
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx = malloc(sizeof(Dav1dPlayRendererPrivateContext));
|
||||
if (rd_priv_ctx == NULL) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
return NULL;
|
||||
}
|
||||
rd_priv_ctx->win = win;
|
||||
|
||||
// Create renderer
|
||||
rd_priv_ctx->renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
|
||||
// Set scale quality
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
|
||||
|
||||
// Create Mutex
|
||||
rd_priv_ctx->lock = SDL_CreateMutex();
|
||||
if (rd_priv_ctx->lock == NULL) {
|
||||
fprintf(stderr, "SDL_CreateMutex failed: %s\n", SDL_GetError());
|
||||
free(rd_priv_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rd_priv_ctx->tex = NULL;
|
||||
|
||||
return rd_priv_ctx;
|
||||
}
|
||||
|
||||
static void sdl_renderer_destroy(void *cookie)
|
||||
{
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
|
||||
assert(rd_priv_ctx != NULL);
|
||||
|
||||
SDL_DestroyTexture(rd_priv_ctx->tex);
|
||||
SDL_DestroyRenderer(rd_priv_ctx->renderer);
|
||||
SDL_DestroyWindow(rd_priv_ctx->win);
|
||||
SDL_DestroyMutex(rd_priv_ctx->lock);
|
||||
free(rd_priv_ctx);
|
||||
}
|
||||
|
||||
static void sdl_render(void *cookie, const Dav1dPlaySettings *settings)
|
||||
{
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
|
||||
assert(rd_priv_ctx != NULL);
|
||||
|
||||
SDL_LockMutex(rd_priv_ctx->lock);
|
||||
|
||||
if (rd_priv_ctx->tex == NULL) {
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
// Display the frame
|
||||
SDL_RenderClear(rd_priv_ctx->renderer);
|
||||
SDL_RenderCopy(rd_priv_ctx->renderer, rd_priv_ctx->tex, NULL, NULL);
|
||||
SDL_RenderPresent(rd_priv_ctx->renderer);
|
||||
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
}
|
||||
|
||||
static int sdl_update_texture(void *cookie, Dav1dPicture *dav1d_pic,
|
||||
const Dav1dPlaySettings *settings)
|
||||
{
|
||||
Dav1dPlayRendererPrivateContext *rd_priv_ctx = cookie;
|
||||
assert(rd_priv_ctx != NULL);
|
||||
|
||||
SDL_LockMutex(rd_priv_ctx->lock);
|
||||
|
||||
if (dav1d_pic == NULL) {
|
||||
rd_priv_ctx->tex = NULL;
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int width = dav1d_pic->p.w;
|
||||
int height = dav1d_pic->p.h;
|
||||
int tex_w = width;
|
||||
int tex_h = height;
|
||||
|
||||
enum Dav1dPixelLayout dav1d_layout = dav1d_pic->p.layout;
|
||||
|
||||
if (DAV1D_PIXEL_LAYOUT_I420 != dav1d_layout || dav1d_pic->p.bpc != 8) {
|
||||
fprintf(stderr, "Unsupported pixel format, only 8bit 420 supported so far.\n");
|
||||
exit(50);
|
||||
}
|
||||
|
||||
SDL_Texture *texture = rd_priv_ctx->tex;
|
||||
if (texture != NULL) {
|
||||
SDL_QueryTexture(texture, NULL, NULL, &tex_w, &tex_h);
|
||||
if (tex_w != width || tex_h != height) {
|
||||
SDL_DestroyTexture(texture);
|
||||
texture = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (texture == NULL) {
|
||||
texture = SDL_CreateTexture(rd_priv_ctx->renderer, SDL_PIXELFORMAT_IYUV,
|
||||
SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
SDL_RenderSetLogicalSize(rd_priv_ctx->renderer, width, height);
|
||||
}
|
||||
|
||||
SDL_UpdateYUVTexture(texture, NULL,
|
||||
dav1d_pic->data[0], (int)dav1d_pic->stride[0], // Y
|
||||
dav1d_pic->data[1], (int)dav1d_pic->stride[1], // U
|
||||
dav1d_pic->data[2], (int)dav1d_pic->stride[1] // V
|
||||
);
|
||||
|
||||
rd_priv_ctx->tex = texture;
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Dav1dPlayRenderInfo rdr_sdl = {
|
||||
.name = "sdl",
|
||||
.create_renderer = sdl_renderer_create,
|
||||
.destroy_renderer = sdl_renderer_destroy,
|
||||
.render = sdl_render,
|
||||
.update_frame = sdl_update_texture
|
||||
};
|
||||
78
media/libdav1d/src/examples/meson.build
Normal file
78
media/libdav1d/src/examples/meson.build
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# Copyright © 2018, VideoLAN and dav1d authors
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#
|
||||
# Build definition for the dav1d examples
|
||||
#
|
||||
|
||||
# Leave subdir if examples are disabled
|
||||
if not get_option('enable_examples')
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
|
||||
# dav1d player sources
|
||||
dav1dplay_sources = files(
|
||||
'dav1dplay.c',
|
||||
'dp_fifo.c',
|
||||
'dp_renderer_placebo.c',
|
||||
'dp_renderer_sdl.c',
|
||||
)
|
||||
|
||||
sdl2_dependency = dependency('sdl2', version: '>= 2.0.1', required: true)
|
||||
|
||||
if sdl2_dependency.found()
|
||||
dav1dplay_deps = [sdl2_dependency, libm_dependency]
|
||||
dav1dplay_cflags = []
|
||||
|
||||
placebo_dependency = dependency('libplacebo', version: '>= 4.160.0', required: false)
|
||||
|
||||
have_vulkan = false
|
||||
have_placebo = placebo_dependency.found()
|
||||
if have_placebo
|
||||
dav1dplay_deps += placebo_dependency
|
||||
|
||||
# If libplacebo is found, we might be able to use Vulkan
|
||||
# with it, in which case we need the Vulkan library too.
|
||||
vulkan_dependency = dependency('vulkan', required: false)
|
||||
if vulkan_dependency.found()
|
||||
dav1dplay_deps += vulkan_dependency
|
||||
have_vulkan = true
|
||||
endif
|
||||
endif
|
||||
|
||||
dav1dplay_cflags += '-DHAVE_PLACEBO=' + (have_placebo ? '1' : '0')
|
||||
dav1dplay_cflags += '-DHAVE_VULKAN=' + (have_vulkan ? '1' : '0')
|
||||
|
||||
dav1dplay = executable('dav1dplay',
|
||||
dav1dplay_sources,
|
||||
rev_target,
|
||||
|
||||
link_with : [libdav1d, dav1d_input_objs],
|
||||
include_directories : [dav1d_inc_dirs],
|
||||
dependencies : [getopt_dependency, dav1dplay_deps],
|
||||
install : true,
|
||||
c_args : dav1dplay_cflags,
|
||||
)
|
||||
endif
|
||||
4
media/libdav1d/src/gcovr.cfg
Normal file
4
media/libdav1d/src/gcovr.cfg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
exclude = .*/tests/.*
|
||||
exclude = .*/tools/.*
|
||||
exclude = .*/include/common/dump.h
|
||||
gcov-ignore-parse-errors = negative_hits.warn
|
||||
213
media/libdav1d/src/include/common/attributes.h
Normal file
213
media/libdav1d/src/include/common/attributes.h
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_COMMON_ATTRIBUTES_H
|
||||
#define DAV1D_COMMON_ATTRIBUTES_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ATTR_ALIAS __attribute__((may_alias))
|
||||
#if defined(__MINGW32__) && !defined(__clang__)
|
||||
#define ATTR_FORMAT_PRINTF(fmt, attr) __attribute__((__format__(__gnu_printf__, fmt, attr)))
|
||||
#else
|
||||
#define ATTR_FORMAT_PRINTF(fmt, attr) __attribute__((__format__(__printf__, fmt, attr)))
|
||||
#endif
|
||||
#define COLD __attribute__((cold))
|
||||
#else
|
||||
#define ATTR_ALIAS
|
||||
#define ATTR_FORMAT_PRINTF(fmt, attr)
|
||||
#define COLD
|
||||
#endif
|
||||
|
||||
#if ARCH_X86_64
|
||||
/* x86-64 needs 32- and 64-byte alignment for AVX2 and AVX-512. */
|
||||
#define ALIGN_64_VAL 64
|
||||
#define ALIGN_32_VAL 32
|
||||
#define ALIGN_16_VAL 16
|
||||
#elif ARCH_AARCH64 || ARCH_ARM || ARCH_LOONGARCH || ARCH_PPC64LE || ARCH_X86_32
|
||||
/* ARM doesn't benefit from anything more than 16-byte alignment. */
|
||||
#define ALIGN_64_VAL 16
|
||||
#define ALIGN_32_VAL 16
|
||||
#define ALIGN_16_VAL 16
|
||||
#else
|
||||
/* No need for extra alignment on platforms without assembly. */
|
||||
#define ALIGN_64_VAL 8
|
||||
#define ALIGN_32_VAL 8
|
||||
#define ALIGN_16_VAL 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* API for variables, struct members (ALIGN()) like:
|
||||
* uint8_t var[1][2][3][4]
|
||||
* becomes:
|
||||
* ALIGN(uint8_t var[1][2][3][4], alignment).
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#define ALIGN(ll, a) \
|
||||
__declspec(align(a)) ll
|
||||
#else
|
||||
#define ALIGN(line, align) \
|
||||
line __attribute__((aligned(align)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* API for stack alignment (ALIGN_STK_$align()) of variables like:
|
||||
* uint8_t var[1][2][3][4]
|
||||
* becomes:
|
||||
* ALIGN_STK_$align(uint8_t, var, 1, [2][3][4])
|
||||
*/
|
||||
#define ALIGN_STK_64(type, var, sz1d, sznd) \
|
||||
ALIGN(type var[sz1d]sznd, ALIGN_64_VAL)
|
||||
#define ALIGN_STK_32(type, var, sz1d, sznd) \
|
||||
ALIGN(type var[sz1d]sznd, ALIGN_32_VAL)
|
||||
#define ALIGN_STK_16(type, var, sz1d, sznd) \
|
||||
ALIGN(type var[sz1d]sznd, ALIGN_16_VAL)
|
||||
|
||||
/*
|
||||
* Forbid inlining of a function:
|
||||
* static NOINLINE void func() {}
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#define NOINLINE __declspec(noinline)
|
||||
#elif __has_attribute(noclone)
|
||||
#define NOINLINE __attribute__((noinline, noclone))
|
||||
#else
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
#define ALWAYS_INLINE __attribute__((always_inline)) inline
|
||||
#endif
|
||||
|
||||
#if (defined(__ELF__) || defined(__MACH__) || (defined(_WIN32) && defined(__clang__))) && __has_attribute(visibility)
|
||||
#define EXTERN extern __attribute__((visibility("hidden")))
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#if ARCH_X86_64 && __has_attribute(model)
|
||||
#define ATTR_MCMODEL_SMALL __attribute__((model("small")))
|
||||
#else
|
||||
#define ATTR_MCMODEL_SMALL
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#define NO_SANITIZE(x) __attribute__((no_sanitize(x)))
|
||||
#else
|
||||
#define NO_SANITIZE(x)
|
||||
#endif
|
||||
|
||||
#if defined(NDEBUG) && (defined(__GNUC__) || defined(__clang__))
|
||||
#undef assert
|
||||
#define assert(x) do { if (!(x)) __builtin_unreachable(); } while (0)
|
||||
#elif defined(NDEBUG) && defined(_MSC_VER)
|
||||
#undef assert
|
||||
#define assert __assume
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||
# define dav1d_uninit(x) x=x
|
||||
#else
|
||||
# define dav1d_uninit(x) x
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#include <intrin.h>
|
||||
|
||||
static inline int ctz(const unsigned int mask) {
|
||||
unsigned long idx;
|
||||
_BitScanForward(&idx, mask);
|
||||
return idx;
|
||||
}
|
||||
|
||||
static inline int clz(const unsigned int mask) {
|
||||
unsigned long leading_zero = 0;
|
||||
_BitScanReverse(&leading_zero, mask);
|
||||
return (31 - leading_zero);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
static inline int clzll(const unsigned long long mask) {
|
||||
unsigned long leading_zero = 0;
|
||||
_BitScanReverse64(&leading_zero, mask);
|
||||
return (63 - leading_zero);
|
||||
}
|
||||
#else /* _WIN64 */
|
||||
static inline int clzll(const unsigned long long mask) {
|
||||
if (mask >> 32)
|
||||
return clz((unsigned)(mask >> 32));
|
||||
else
|
||||
return clz((unsigned)mask) + 32;
|
||||
}
|
||||
#endif /* _WIN64 */
|
||||
#else /* !_MSC_VER */
|
||||
static inline int ctz(const unsigned int mask) {
|
||||
return __builtin_ctz(mask);
|
||||
}
|
||||
|
||||
static inline int clz(const unsigned int mask) {
|
||||
return __builtin_clz(mask);
|
||||
}
|
||||
|
||||
static inline int clzll(const unsigned long long mask) {
|
||||
return __builtin_clzll(mask);
|
||||
}
|
||||
#endif /* !_MSC_VER */
|
||||
|
||||
#ifndef static_assert
|
||||
#define CHECK_OFFSET(type, field, name) \
|
||||
struct check_##type##_##field { int x[(name == offsetof(type, field)) ? 1 : -1]; }
|
||||
#define CHECK_SIZE(type, size) \
|
||||
struct check_##type##_size { int x[(size == sizeof(type)) ? 1 : -1]; }
|
||||
#else
|
||||
#define CHECK_OFFSET(type, field, name) \
|
||||
static_assert(name == offsetof(type, field), #field)
|
||||
#define CHECK_SIZE(type, size) \
|
||||
static_assert(size == sizeof(type), #type)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define PACKED(...) __pragma(pack(push, 1)) __VA_ARGS__ __pragma(pack(pop))
|
||||
#else
|
||||
#define PACKED(...) __VA_ARGS__ __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_COMMON_ATTRIBUTES_H */
|
||||
93
media/libdav1d/src/include/common/bitdepth.h
Normal file
93
media/libdav1d/src/include/common/bitdepth.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_COMMON_BITDEPTH_H
|
||||
#define DAV1D_COMMON_BITDEPTH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/attributes.h"
|
||||
|
||||
#if !defined(BITDEPTH)
|
||||
typedef uint8_t pixel; /* can't be void due to pointer-to-array usage */
|
||||
typedef void coef;
|
||||
#define HIGHBD_DECL_SUFFIX /* nothing */
|
||||
#define HIGHBD_CALL_SUFFIX /* nothing */
|
||||
#define HIGHBD_TAIL_SUFFIX /* nothing */
|
||||
#elif BITDEPTH == 8
|
||||
typedef uint8_t pixel;
|
||||
typedef int16_t coef;
|
||||
#define PIXEL_TYPE uint8_t
|
||||
#define COEF_TYPE int16_t
|
||||
#define pixel_copy memcpy
|
||||
#define pixel_set memset
|
||||
#define iclip_pixel iclip_u8
|
||||
#define PIX_HEX_FMT "%02x"
|
||||
#define bitfn(x) x##_8bpc
|
||||
#define BF(x, suffix) x##_8bpc_##suffix
|
||||
#define PXSTRIDE(x) (x)
|
||||
#define highbd_only(x)
|
||||
#define HIGHBD_DECL_SUFFIX /* nothing */
|
||||
#define HIGHBD_CALL_SUFFIX /* nothing */
|
||||
#define HIGHBD_TAIL_SUFFIX /* nothing */
|
||||
#define bitdepth_from_max(x) 8
|
||||
#define BITDEPTH_MAX 0xff
|
||||
#elif BITDEPTH == 16
|
||||
typedef uint16_t pixel;
|
||||
typedef int32_t coef;
|
||||
#define PIXEL_TYPE uint16_t
|
||||
#define COEF_TYPE int32_t
|
||||
#define pixel_copy(a, b, c) memcpy(a, b, (c) << 1)
|
||||
static inline void pixel_set(pixel *const dst, const int val, const int num) {
|
||||
for (int n = 0; n < num; n++)
|
||||
dst[n] = val;
|
||||
}
|
||||
#define PIX_HEX_FMT "%03x"
|
||||
#define iclip_pixel(x) iclip(x, 0, bitdepth_max)
|
||||
#define HIGHBD_DECL_SUFFIX , const int bitdepth_max
|
||||
#define HIGHBD_CALL_SUFFIX , f->bitdepth_max
|
||||
#define HIGHBD_TAIL_SUFFIX , bitdepth_max
|
||||
#define bitdepth_from_max(bitdepth_max) (32 - clz(bitdepth_max))
|
||||
#define BITDEPTH_MAX bitdepth_max
|
||||
#define bitfn(x) x##_16bpc
|
||||
#define BF(x, suffix) x##_16bpc_##suffix
|
||||
static inline ptrdiff_t PXSTRIDE(const ptrdiff_t x) {
|
||||
assert(!(x & 1));
|
||||
return x >> 1;
|
||||
}
|
||||
#define highbd_only(x) x
|
||||
#else
|
||||
#error invalid value for bitdepth
|
||||
#endif
|
||||
#define bytefn(x) bitfn(x)
|
||||
|
||||
#define bitfn_decls(name, ...) \
|
||||
name##_8bpc(__VA_ARGS__); \
|
||||
name##_16bpc(__VA_ARGS__)
|
||||
|
||||
#endif /* DAV1D_COMMON_BITDEPTH_H */
|
||||
92
media/libdav1d/src/include/common/dump.h
Normal file
92
media/libdav1d/src/include/common/dump.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_COMMON_DUMP_H
|
||||
#define DAV1D_COMMON_DUMP_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common/bitdepth.h"
|
||||
|
||||
static inline void append_plane_to_file(const pixel *buf, ptrdiff_t stride,
|
||||
int w, int h, const char *const file)
|
||||
{
|
||||
FILE *const f = fopen(file, "ab");
|
||||
while (h--) {
|
||||
fwrite(buf, w * sizeof(pixel), 1, f);
|
||||
buf += PXSTRIDE(stride);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static inline void hex_fdump(FILE *out, const pixel *buf, ptrdiff_t stride,
|
||||
int w, int h, const char *what)
|
||||
{
|
||||
fprintf(out, "%s\n", what);
|
||||
while (h--) {
|
||||
int x;
|
||||
for (x = 0; x < w; x++)
|
||||
fprintf(out, " " PIX_HEX_FMT, buf[x]);
|
||||
buf += PXSTRIDE(stride);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hex_dump(const pixel *buf, ptrdiff_t stride,
|
||||
int w, int h, const char *what)
|
||||
{
|
||||
hex_fdump(stdout, buf, stride, w, h, what);
|
||||
}
|
||||
|
||||
static inline void coef_dump(const coef *buf, const int w, const int h,
|
||||
const int len, const char *what)
|
||||
{
|
||||
int y;
|
||||
printf("%s\n", what);
|
||||
for (y = 0; y < h; y++) {
|
||||
int x;
|
||||
for (x = 0; x < w; x++)
|
||||
printf(" %*d", len, buf[x]);
|
||||
buf += w;
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ac_dump(const int16_t *buf, int w, int h, const char *what)
|
||||
{
|
||||
printf("%s\n", what);
|
||||
while (h--) {
|
||||
for (int x = 0; x < w; x++)
|
||||
printf(" %03d", buf[x]);
|
||||
buf += w;
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DAV1D_COMMON_DUMP_H */
|
||||
45
media/libdav1d/src/include/common/frame.h
Normal file
45
media/libdav1d/src/include/common/frame.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright © 2021, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_COMMON_FRAME_H
|
||||
#define DAV1D_COMMON_FRAME_H
|
||||
|
||||
/*
|
||||
* Checks whether Dav1dFrameType == INTER || == SWITCH
|
||||
* Both are defined as odd numbers {1, 3} and therefore have the LSB set.
|
||||
* See also: AV1 spec 6.8.2
|
||||
*/
|
||||
#define IS_INTER_OR_SWITCH(frame_header) \
|
||||
((frame_header)->frame_type & 1)
|
||||
|
||||
/*
|
||||
* Checks whether Dav1dFrameType == KEY || == INTRA
|
||||
* See also: AV1 spec 6.8.2
|
||||
*/
|
||||
#define IS_KEY_OR_INTRA(frame_header) \
|
||||
(!IS_INTER_OR_SWITCH(frame_header))
|
||||
|
||||
#endif /* DAV1D_COMMON_FRAME_H */
|
||||
84
media/libdav1d/src/include/common/intops.h
Normal file
84
media/libdav1d/src/include/common/intops.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_COMMON_INTOPS_H
|
||||
#define DAV1D_COMMON_INTOPS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common/attributes.h"
|
||||
|
||||
static inline int imax(const int a, const int b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
static inline int imin(const int a, const int b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
static inline unsigned umax(const unsigned a, const unsigned b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
static inline unsigned umin(const unsigned a, const unsigned b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
static inline int iclip(const int v, const int min, const int max) {
|
||||
return v < min ? min : v > max ? max : v;
|
||||
}
|
||||
|
||||
static inline int iclip_u8(const int v) {
|
||||
return iclip(v, 0, 255);
|
||||
}
|
||||
|
||||
static inline int apply_sign(const int v, const int s) {
|
||||
return s < 0 ? -v : v;
|
||||
}
|
||||
|
||||
static inline int apply_sign64(const int v, const int64_t s) {
|
||||
return s < 0 ? -v : v;
|
||||
}
|
||||
|
||||
static inline int ulog2(const unsigned v) {
|
||||
return 31 ^ clz(v);
|
||||
}
|
||||
|
||||
static inline int u64log2(const uint64_t v) {
|
||||
return 63 ^ clzll(v);
|
||||
}
|
||||
|
||||
static inline unsigned inv_recenter(const unsigned r, const unsigned v) {
|
||||
if (v > (r << 1))
|
||||
return v;
|
||||
else if ((v & 1) == 0)
|
||||
return (v >> 1) + r;
|
||||
else
|
||||
return r - ((v + 1) >> 1);
|
||||
}
|
||||
|
||||
#endif /* DAV1D_COMMON_INTOPS_H */
|
||||
61
media/libdav1d/src/include/common/validate.h
Normal file
61
media/libdav1d/src/include/common/validate.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_COMMON_VALIDATE_H
|
||||
#define DAV1D_COMMON_VALIDATE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(NDEBUG)
|
||||
#define debug_print(...) do {} while (0)
|
||||
#define debug_abort() do {} while (0)
|
||||
#else
|
||||
#define debug_print(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define debug_abort abort
|
||||
#endif
|
||||
|
||||
#define validate_input_or_ret_with_msg(x, r, ...) \
|
||||
if (!(x)) { \
|
||||
debug_print("Input validation check \'%s\' failed in %s!\n", \
|
||||
#x, __func__); \
|
||||
debug_print(__VA_ARGS__); \
|
||||
debug_abort(); \
|
||||
return r; \
|
||||
}
|
||||
|
||||
#define validate_input_or_ret(x, r) \
|
||||
if (!(x)) { \
|
||||
debug_print("Input validation check \'%s\' failed in %s!\n", \
|
||||
#x, __func__); \
|
||||
debug_abort(); \
|
||||
return r; \
|
||||
}
|
||||
|
||||
#define validate_input(x) validate_input_or_ret(x, )
|
||||
|
||||
#endif /* DAV1D_COMMON_VALIDATE_H */
|
||||
51
media/libdav1d/src/include/compat/gcc/stdatomic.h
Normal file
51
media/libdav1d/src/include/compat/gcc/stdatomic.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GCCVER_STDATOMIC_H_
|
||||
#define GCCVER_STDATOMIC_H_
|
||||
|
||||
#if !defined(__cplusplus)
|
||||
|
||||
typedef int atomic_int;
|
||||
typedef unsigned int atomic_uint;
|
||||
|
||||
#define memory_order_relaxed __ATOMIC_RELAXED
|
||||
#define memory_order_acquire __ATOMIC_ACQUIRE
|
||||
|
||||
#define atomic_init(p_a, v) do { *(p_a) = (v); } while(0)
|
||||
#define atomic_store(p_a, v) __atomic_store_n(p_a, v, __ATOMIC_SEQ_CST)
|
||||
#define atomic_load(p_a) __atomic_load_n(p_a, __ATOMIC_SEQ_CST)
|
||||
#define atomic_load_explicit(p_a, mo) __atomic_load_n(p_a, mo)
|
||||
#define atomic_fetch_add(p_a, inc) __atomic_fetch_add(p_a, inc, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_add_explicit(p_a, inc, mo) __atomic_fetch_add(p_a, inc, mo)
|
||||
#define atomic_fetch_sub(p_a, dec) __atomic_fetch_sub(p_a, dec, __ATOMIC_SEQ_CST)
|
||||
#define atomic_exchange(p_a, v) __atomic_exchange_n(p_a, v, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_or(p_a, v) __atomic_fetch_or(p_a, v, __ATOMIC_SEQ_CST)
|
||||
#define atomic_compare_exchange_strong(p_a, expected, desired) __atomic_compare_exchange_n(p_a, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
|
||||
#endif /* !defined(__cplusplus) */
|
||||
|
||||
#endif /* GCCVER_STDATOMIC_H_ */
|
||||
97
media/libdav1d/src/include/compat/getopt.h
Normal file
97
media/libdav1d/src/include/compat/getopt.h
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#ifndef __GETOPT_H__
|
||||
/**
|
||||
* DISCLAIMER
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file is part of the mingw-w64 runtime package.
|
||||
*
|
||||
* The mingw-w64 runtime package and its code is distributed in the hope that it
|
||||
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
|
||||
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
|
||||
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#define __GETOPT_H__
|
||||
|
||||
/* All the headers include this file. */
|
||||
#ifdef _WIN32
|
||||
#include <crtdefs.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int optind; /* index of first non-option in argv */
|
||||
extern int optopt; /* single option character, as parsed */
|
||||
extern int opterr; /* flag to enable built-in diagnostics... */
|
||||
/* (user may set to zero, to suppress) */
|
||||
|
||||
extern char *optarg; /* pointer to argument of current option */
|
||||
|
||||
extern int getopt(int nargc, char * const *nargv, const char *options);
|
||||
|
||||
#ifdef _BSD_SOURCE
|
||||
/*
|
||||
* BSD adds the non-standard `optreset' feature, for reinitialisation
|
||||
* of `getopt' parsing. We support this feature, for applications which
|
||||
* proclaim their BSD heritage, before including this header; however,
|
||||
* to maintain portability, developers are advised to avoid it.
|
||||
*/
|
||||
# define optreset __mingw_optreset
|
||||
extern int optreset;
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* POSIX requires the `getopt' API to be specified in `unistd.h';
|
||||
* thus, `unistd.h' includes this header. However, we do not want
|
||||
* to expose the `getopt_long' or `getopt_long_only' APIs, when
|
||||
* included in this manner. Thus, close the standard __GETOPT_H__
|
||||
* declarations block, and open an additional __GETOPT_LONG_H__
|
||||
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
|
||||
* to declare the extended API.
|
||||
*/
|
||||
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
|
||||
#define __GETOPT_LONG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct option /* specification for a long form option... */
|
||||
{
|
||||
const char *name; /* option name, without leading hyphens */
|
||||
int has_arg; /* does it take an argument? */
|
||||
int *flag; /* where to save its status, or NULL */
|
||||
int val; /* its associated status value */
|
||||
};
|
||||
|
||||
enum /* permitted values for its `has_arg' field... */
|
||||
{
|
||||
no_argument = 0, /* option never takes an argument */
|
||||
required_argument, /* option always requires an argument */
|
||||
optional_argument /* option may take an argument */
|
||||
};
|
||||
|
||||
extern int getopt_long(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx);
|
||||
extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx);
|
||||
/*
|
||||
* Previous MinGW implementation had...
|
||||
*/
|
||||
#ifndef HAVE_DECL_GETOPT
|
||||
/*
|
||||
* ...for the long form API only; keep this for compatibility.
|
||||
*/
|
||||
# define HAVE_DECL_GETOPT 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
|
||||
|
||||
#endif /* !defined(__GETOPT_H__) */
|
||||
82
media/libdav1d/src/include/compat/msvc/stdatomic.h
Normal file
82
media/libdav1d/src/include/compat/msvc/stdatomic.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MSCVER_STDATOMIC_H_
|
||||
#define MSCVER_STDATOMIC_H_
|
||||
|
||||
#if !defined(__cplusplus) && defined(_MSC_VER)
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4067) /* newline for __has_include_next */
|
||||
|
||||
#if defined(__clang__) && __has_include_next(<stdatomic.h>)
|
||||
/* use the clang stdatomic.h with clang-cl*/
|
||||
# include_next <stdatomic.h>
|
||||
#else /* ! stdatomic.h */
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "common/attributes.h"
|
||||
|
||||
typedef volatile LONG atomic_int;
|
||||
typedef volatile ULONG atomic_uint;
|
||||
|
||||
typedef enum {
|
||||
memory_order_relaxed,
|
||||
memory_order_acquire
|
||||
} msvc_atomic_memory_order;
|
||||
|
||||
#define atomic_init(p_a, v) do { *(p_a) = (v); } while(0)
|
||||
#define atomic_store(p_a, v) InterlockedExchange((LONG*)p_a, v)
|
||||
#define atomic_load(p_a) InterlockedCompareExchange((LONG*)p_a, 0, 0)
|
||||
#define atomic_exchange(p_a, v) InterlockedExchange(p_a, v)
|
||||
#define atomic_load_explicit(p_a, mo) atomic_load(p_a)
|
||||
|
||||
static inline int atomic_compare_exchange_strong_int(LONG *obj, LONG *expected,
|
||||
LONG desired)
|
||||
{
|
||||
LONG orig = *expected;
|
||||
*expected = InterlockedCompareExchange(obj, desired, orig);
|
||||
return *expected == orig;
|
||||
}
|
||||
#define atomic_compare_exchange_strong(p_a, expected, desired) atomic_compare_exchange_strong_int((LONG *)p_a, (LONG *)expected, (LONG)desired)
|
||||
|
||||
/*
|
||||
* TODO use a special call to increment/decrement
|
||||
* using InterlockedIncrement/InterlockedDecrement
|
||||
*/
|
||||
#define atomic_fetch_add(p_a, inc) InterlockedExchangeAdd(p_a, inc)
|
||||
#define atomic_fetch_sub(p_a, dec) InterlockedExchangeAdd(p_a, -(dec))
|
||||
#define atomic_fetch_or(p_a, v) InterlockedOr(p_a, v)
|
||||
#define atomic_fetch_add_explicit(p_a, inc, mo) atomic_fetch_add(p_a, inc)
|
||||
|
||||
#endif /* ! stdatomic.h */
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif /* !defined(__cplusplus) && defined(_MSC_VER) */
|
||||
|
||||
#endif /* MSCVER_STDATOMIC_H_ */
|
||||
94
media/libdav1d/src/include/dav1d/common.h
Normal file
94
media/libdav1d/src/include/dav1d/common.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_COMMON_H
|
||||
#define DAV1D_COMMON_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef DAV1D_API
|
||||
#if defined _WIN32
|
||||
#if defined DAV1D_BUILDING_DLL
|
||||
#define DAV1D_API __declspec(dllexport)
|
||||
#else
|
||||
#define DAV1D_API
|
||||
#endif
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define DAV1D_API __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define DAV1D_API
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if EPERM > 0
|
||||
#define DAV1D_ERR(e) (-(e)) ///< Negate POSIX error code.
|
||||
#else
|
||||
#define DAV1D_ERR(e) (e)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A reference-counted object wrapper for a user-configurable pointer.
|
||||
*/
|
||||
typedef struct Dav1dUserData {
|
||||
const uint8_t *data; ///< data pointer
|
||||
struct Dav1dRef *ref; ///< allocation origin
|
||||
} Dav1dUserData;
|
||||
|
||||
/**
|
||||
* Input packet metadata which are copied from the input data used to
|
||||
* decode each image into the matching structure of the output image
|
||||
* returned back to the user. Since these are metadata fields, they
|
||||
* can be used for other purposes than the documented ones, they will
|
||||
* still be passed from input data to output picture without being
|
||||
* used internally.
|
||||
*/
|
||||
typedef struct Dav1dDataProps {
|
||||
int64_t timestamp; ///< container timestamp of input data, INT64_MIN if unknown (default)
|
||||
int64_t duration; ///< container duration of input data, 0 if unknown (default)
|
||||
int64_t offset; ///< stream offset of input data, -1 if unknown (default)
|
||||
size_t size; ///< packet size, default Dav1dData.sz
|
||||
struct Dav1dUserData user_data; ///< user-configurable data, default NULL members
|
||||
} Dav1dDataProps;
|
||||
|
||||
/**
|
||||
* Release reference to a Dav1dDataProps.
|
||||
*/
|
||||
DAV1D_API void dav1d_data_props_unref(Dav1dDataProps *props);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_COMMON_H */
|
||||
117
media/libdav1d/src/include/dav1d/data.h
Normal file
117
media/libdav1d/src/include/dav1d/data.h
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_DATA_H
|
||||
#define DAV1D_DATA_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Dav1dData {
|
||||
const uint8_t *data; ///< data pointer
|
||||
size_t sz; ///< data size
|
||||
struct Dav1dRef *ref; ///< allocation origin
|
||||
Dav1dDataProps m; ///< user provided metadata passed to the output picture
|
||||
} Dav1dData;
|
||||
|
||||
/**
|
||||
* Allocate data.
|
||||
*
|
||||
* @param data Input context.
|
||||
* @param sz Size of the data that should be allocated.
|
||||
*
|
||||
* @return Pointer to the allocated buffer on success. NULL on error.
|
||||
*/
|
||||
DAV1D_API uint8_t * dav1d_data_create(Dav1dData *data, size_t sz);
|
||||
|
||||
/**
|
||||
* Wrap an existing data array.
|
||||
*
|
||||
* @param data Input context.
|
||||
* @param buf The data to be wrapped.
|
||||
* @param sz Size of the data.
|
||||
* @param free_callback Function to be called when we release our last
|
||||
* reference to this data. In this callback, $buf will be
|
||||
* the $buf argument to this function, and $cookie will
|
||||
* be the $cookie input argument to this function.
|
||||
* @param cookie Opaque parameter passed to free_callback().
|
||||
*
|
||||
* @return 0 on success. A negative DAV1D_ERR value on error.
|
||||
*/
|
||||
DAV1D_API int dav1d_data_wrap(Dav1dData *data, const uint8_t *buf, size_t sz,
|
||||
void (*free_callback)(const uint8_t *buf, void *cookie),
|
||||
void *cookie);
|
||||
|
||||
/**
|
||||
* Wrap a user-provided data pointer into a reference counted object.
|
||||
*
|
||||
* data->m.user_data field will initialized to wrap the provided $user_data
|
||||
* pointer.
|
||||
*
|
||||
* $free_callback will be called on the same thread that released the last
|
||||
* reference. If frame threading is used, make sure $free_callback is
|
||||
* thread-safe.
|
||||
*
|
||||
* @param data Input context.
|
||||
* @param user_data The user data to be wrapped.
|
||||
* @param free_callback Function to be called when we release our last
|
||||
* reference to this data. In this callback, $user_data
|
||||
* will be the $user_data argument to this function, and
|
||||
* $cookie will be the $cookie input argument to this
|
||||
* function.
|
||||
* @param cookie Opaque parameter passed to $free_callback.
|
||||
*
|
||||
* @return 0 on success. A negative DAV1D_ERR value on error.
|
||||
*/
|
||||
DAV1D_API int dav1d_data_wrap_user_data(Dav1dData *data,
|
||||
const uint8_t *user_data,
|
||||
void (*free_callback)(const uint8_t *user_data,
|
||||
void *cookie),
|
||||
void *cookie);
|
||||
|
||||
/**
|
||||
* Free the data reference.
|
||||
*
|
||||
* The reference count for data->m.user_data will be decremented (if it has been
|
||||
* initialized with dav1d_data_wrap_user_data). The $data object will be memset
|
||||
* to 0.
|
||||
*
|
||||
* @param data Input context.
|
||||
*/
|
||||
DAV1D_API void dav1d_data_unref(Dav1dData *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_DATA_H */
|
||||
329
media/libdav1d/src/include/dav1d/dav1d.h
Normal file
329
media/libdav1d/src/include/dav1d/dav1d.h
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright © 2018-2021, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_H
|
||||
#define DAV1D_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "picture.h"
|
||||
#include "data.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Dav1dContext Dav1dContext;
|
||||
typedef struct Dav1dRef Dav1dRef;
|
||||
|
||||
#define DAV1D_MAX_THREADS 256
|
||||
#define DAV1D_MAX_FRAME_DELAY 256
|
||||
|
||||
typedef struct Dav1dLogger {
|
||||
void *cookie; ///< Custom data to pass to the callback.
|
||||
/**
|
||||
* Logger callback. May be NULL to disable logging.
|
||||
*
|
||||
* @param cookie Custom pointer passed to all calls.
|
||||
* @param format The vprintf compatible format string.
|
||||
* @param ap List of arguments referenced by the format string.
|
||||
*/
|
||||
void (*callback)(void *cookie, const char *format, va_list ap);
|
||||
} Dav1dLogger;
|
||||
|
||||
enum Dav1dInloopFilterType {
|
||||
DAV1D_INLOOPFILTER_NONE = 0,
|
||||
DAV1D_INLOOPFILTER_DEBLOCK = 1 << 0,
|
||||
DAV1D_INLOOPFILTER_CDEF = 1 << 1,
|
||||
DAV1D_INLOOPFILTER_RESTORATION = 1 << 2,
|
||||
DAV1D_INLOOPFILTER_ALL = DAV1D_INLOOPFILTER_DEBLOCK |
|
||||
DAV1D_INLOOPFILTER_CDEF |
|
||||
DAV1D_INLOOPFILTER_RESTORATION,
|
||||
};
|
||||
|
||||
enum Dav1dDecodeFrameType {
|
||||
DAV1D_DECODEFRAMETYPE_ALL = 0, ///< decode and return all frames
|
||||
DAV1D_DECODEFRAMETYPE_REFERENCE = 1,///< decode and return frames referenced by other frames only
|
||||
DAV1D_DECODEFRAMETYPE_INTRA = 2, ///< decode and return intra frames only (includes keyframes)
|
||||
DAV1D_DECODEFRAMETYPE_KEY = 3, ///< decode and return keyframes only
|
||||
};
|
||||
|
||||
typedef struct Dav1dSettings {
|
||||
int n_threads; ///< number of threads (0 = number of logical cores in host system, default 0)
|
||||
int max_frame_delay; ///< Set to 1 for low-latency decoding (0 = ceil(sqrt(n_threads)), default 0)
|
||||
int apply_grain; ///< whether to apply film grain on output frames (default 1)
|
||||
int operating_point; ///< select an operating point for scalable AV1 bitstreams (0 - 31, default 0)
|
||||
int all_layers; ///< output all spatial layers of a scalable AV1 biststream (default 1)
|
||||
unsigned frame_size_limit; ///< maximum frame size, in pixels (0 = unlimited, default 0)
|
||||
Dav1dPicAllocator allocator; ///< Picture allocator callback.
|
||||
Dav1dLogger logger; ///< Logger callback.
|
||||
int strict_std_compliance; ///< whether to abort decoding on standard compliance violations
|
||||
///< that don't affect actual bitstream decoding (e.g. inconsistent
|
||||
///< or invalid metadata, default 0)
|
||||
int output_invisible_frames; ///< output invisibly coded frames (in coding order) in addition
|
||||
///< to all visible frames. Because of show-existing-frame, this
|
||||
///< means some frames may appear twice (once when coded,
|
||||
///< once when shown, default 0)
|
||||
enum Dav1dInloopFilterType inloop_filters; ///< postfilters to enable during decoding (default
|
||||
///< DAV1D_INLOOPFILTER_ALL)
|
||||
enum Dav1dDecodeFrameType decode_frame_type; ///< frame types to decode (default
|
||||
///< DAV1D_DECODEFRAMETYPE_ALL)
|
||||
uint8_t reserved[16]; ///< reserved for future use
|
||||
} Dav1dSettings;
|
||||
|
||||
/**
|
||||
* Get library version.
|
||||
*/
|
||||
DAV1D_API const char *dav1d_version(void);
|
||||
|
||||
/**
|
||||
* Get library API version.
|
||||
*
|
||||
* @return A value in the format 0x00XXYYZZ, where XX is the major version,
|
||||
* YY the minor version, and ZZ the patch version.
|
||||
* @see DAV1D_API_MAJOR, DAV1D_API_MINOR, DAV1D_API_PATCH
|
||||
*/
|
||||
DAV1D_API unsigned dav1d_version_api(void);
|
||||
|
||||
/**
|
||||
* Initialize settings to default values.
|
||||
*
|
||||
* @param s Input settings context.
|
||||
*/
|
||||
DAV1D_API void dav1d_default_settings(Dav1dSettings *s);
|
||||
|
||||
/**
|
||||
* Allocate and open a decoder instance.
|
||||
*
|
||||
* @param c_out The decoder instance to open. *c_out will be set to the
|
||||
* allocated context.
|
||||
* @param s Input settings context.
|
||||
*
|
||||
* @note The context must be freed using dav1d_close() when decoding is
|
||||
* finished.
|
||||
*
|
||||
* @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.
|
||||
*/
|
||||
DAV1D_API int dav1d_open(Dav1dContext **c_out, const Dav1dSettings *s);
|
||||
|
||||
/**
|
||||
* Parse a Sequence Header OBU from bitstream data.
|
||||
*
|
||||
* @param out Output Sequence Header.
|
||||
* @param buf The data to be parser.
|
||||
* @param sz Size of the data.
|
||||
*
|
||||
* @return
|
||||
* 0: Success, and out is filled with the parsed Sequence Header
|
||||
* OBU parameters.
|
||||
* DAV1D_ERR(ENOENT): No Sequence Header OBUs were found in the buffer.
|
||||
* Other negative DAV1D_ERR codes: Invalid data in the buffer, invalid passed-in
|
||||
* arguments, and other errors during parsing.
|
||||
*
|
||||
* @note It is safe to feed this function data containing other OBUs than a
|
||||
* Sequence Header, as they will simply be ignored. If there is more than
|
||||
* one Sequence Header OBU present, only the last will be returned.
|
||||
*/
|
||||
DAV1D_API int dav1d_parse_sequence_header(Dav1dSequenceHeader *out,
|
||||
const uint8_t *buf, const size_t sz);
|
||||
|
||||
/**
|
||||
* Feed bitstream data to the decoder, in the form of one or multiple AV1
|
||||
* Open Bitstream Units (OBUs).
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param in Input bitstream data. On success, ownership of the reference is
|
||||
* passed to the library.
|
||||
*
|
||||
* @return
|
||||
* 0: Success, and the data was consumed.
|
||||
* DAV1D_ERR(EAGAIN): The data can't be consumed. dav1d_get_picture() should
|
||||
* be called to get one or more frames before the function
|
||||
* can consume new data.
|
||||
* Other negative DAV1D_ERR codes: Error during decoding or because of invalid
|
||||
* passed-in arguments. The reference remains
|
||||
* owned by the caller.
|
||||
*/
|
||||
DAV1D_API int dav1d_send_data(Dav1dContext *c, Dav1dData *in);
|
||||
|
||||
/**
|
||||
* Return a decoded picture.
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param out Output frame. The caller assumes ownership of the returned
|
||||
* reference.
|
||||
*
|
||||
* @return
|
||||
* 0: Success, and a frame is returned.
|
||||
* DAV1D_ERR(EAGAIN): Not enough data to output a frame. dav1d_send_data()
|
||||
* should be called with new input.
|
||||
* Other negative DAV1D_ERR codes: Error during decoding or because of invalid
|
||||
* passed-in arguments.
|
||||
*
|
||||
* @note To drain buffered frames from the decoder (i.e. on end of stream),
|
||||
* call this function until it returns DAV1D_ERR(EAGAIN).
|
||||
*
|
||||
* @code{.c}
|
||||
* Dav1dData data = { 0 };
|
||||
* Dav1dPicture p = { 0 };
|
||||
* int res;
|
||||
*
|
||||
* read_data(&data);
|
||||
* do {
|
||||
* res = dav1d_send_data(c, &data);
|
||||
* // Keep going even if the function can't consume the current data
|
||||
* packet. It eventually will after one or more frames have been
|
||||
* returned in this loop.
|
||||
* if (res < 0 && res != DAV1D_ERR(EAGAIN))
|
||||
* free_and_abort();
|
||||
* res = dav1d_get_picture(c, &p);
|
||||
* if (res < 0) {
|
||||
* if (res != DAV1D_ERR(EAGAIN))
|
||||
* free_and_abort();
|
||||
* } else
|
||||
* output_and_unref_picture(&p);
|
||||
* // Stay in the loop as long as there's data to consume.
|
||||
* } while (data.sz || read_data(&data) == SUCCESS);
|
||||
*
|
||||
* // Handle EOS by draining all buffered frames.
|
||||
* do {
|
||||
* res = dav1d_get_picture(c, &p);
|
||||
* if (res < 0) {
|
||||
* if (res != DAV1D_ERR(EAGAIN))
|
||||
* free_and_abort();
|
||||
* } else
|
||||
* output_and_unref_picture(&p);
|
||||
* } while (res == 0);
|
||||
* @endcode
|
||||
*/
|
||||
DAV1D_API int dav1d_get_picture(Dav1dContext *c, Dav1dPicture *out);
|
||||
|
||||
/**
|
||||
* Apply film grain to a previously decoded picture. If the picture contains no
|
||||
* film grain metadata, then this function merely returns a new reference.
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param out Output frame. The caller assumes ownership of the returned
|
||||
* reference.
|
||||
* @param in Input frame. No ownership is transferred.
|
||||
*
|
||||
* @return
|
||||
* 0: Success, and a frame is returned.
|
||||
* Other negative DAV1D_ERR codes: Error due to lack of memory or because of
|
||||
* invalid passed-in arguments.
|
||||
*
|
||||
* @note If `Dav1dSettings.apply_grain` is true, film grain was already applied
|
||||
* by `dav1d_get_picture`, and so calling this function leads to double
|
||||
* application of film grain. Users should only call this when needed.
|
||||
*/
|
||||
DAV1D_API int dav1d_apply_grain(Dav1dContext *c, Dav1dPicture *out,
|
||||
const Dav1dPicture *in);
|
||||
|
||||
/**
|
||||
* Close a decoder instance and free all associated memory.
|
||||
*
|
||||
* @param c_out The decoder instance to close. *c_out will be set to NULL.
|
||||
*/
|
||||
DAV1D_API void dav1d_close(Dav1dContext **c_out);
|
||||
|
||||
/**
|
||||
* Flush all delayed frames in decoder and clear internal decoder state,
|
||||
* to be used when seeking.
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
*
|
||||
* @note Decoding will start only after a valid sequence header OBU is
|
||||
* delivered to dav1d_send_data().
|
||||
*
|
||||
*/
|
||||
DAV1D_API void dav1d_flush(Dav1dContext *c);
|
||||
|
||||
enum Dav1dEventFlags {
|
||||
/**
|
||||
* The last returned picture contains a reference to a new Sequence Header,
|
||||
* either because it's the start of a new coded sequence, or the decoder was
|
||||
* flushed before it was generated.
|
||||
*/
|
||||
DAV1D_EVENT_FLAG_NEW_SEQUENCE = 1 << 0,
|
||||
/**
|
||||
* The last returned picture contains a reference to a Sequence Header with
|
||||
* new operating parameters information for the current coded sequence.
|
||||
*/
|
||||
DAV1D_EVENT_FLAG_NEW_OP_PARAMS_INFO = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch a combination of DAV1D_EVENT_FLAG_* event flags generated by the decoding
|
||||
* process.
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param flags Where to write the flags.
|
||||
*
|
||||
* @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.
|
||||
*
|
||||
* @note Calling this function will clear all the event flags currently stored in
|
||||
* the decoder.
|
||||
*
|
||||
*/
|
||||
DAV1D_API int dav1d_get_event_flags(Dav1dContext *c, enum Dav1dEventFlags *flags);
|
||||
|
||||
/**
|
||||
* Retrieve the user-provided metadata associated with the input data packet
|
||||
* for the last decoding error reported to the user, i.e. a negative return
|
||||
* value (not EAGAIN) from dav1d_send_data() or dav1d_get_picture().
|
||||
*
|
||||
* @param c Input decoder instance.
|
||||
* @param out Output Dav1dDataProps. On success, the caller assumes ownership of
|
||||
* the returned reference.
|
||||
*
|
||||
* @return 0 on success, or < 0 (a negative DAV1D_ERR code) on error.
|
||||
*/
|
||||
DAV1D_API int dav1d_get_decode_error_data_props(Dav1dContext *c, Dav1dDataProps *out);
|
||||
|
||||
/**
|
||||
* Get the decoder delay, which is the number of internally buffered frames, not
|
||||
* including reference frames.
|
||||
* This value is guaranteed to be >= 1 and <= max_frame_delay.
|
||||
*
|
||||
* @param s Input settings context.
|
||||
*
|
||||
* @return Decoder frame delay on success, or < 0 (a negative DAV1D_ERR code) on
|
||||
* error.
|
||||
*
|
||||
* @note The returned delay is valid only for a Dav1dContext initialized with the
|
||||
* provided Dav1dSettings.
|
||||
*/
|
||||
DAV1D_API int dav1d_get_frame_delay(const Dav1dSettings *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_H */
|
||||
440
media/libdav1d/src/include/dav1d/headers.h
Normal file
440
media/libdav1d/src/include/dav1d/headers.h
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
/*
|
||||
* Copyright © 2018-2020, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_HEADERS_H
|
||||
#define DAV1D_HEADERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Constants from Section 3. "Symbols and abbreviated terms"
|
||||
#define DAV1D_MAX_CDEF_STRENGTHS 8
|
||||
#define DAV1D_MAX_OPERATING_POINTS 32
|
||||
#define DAV1D_MAX_TILE_COLS 64
|
||||
#define DAV1D_MAX_TILE_ROWS 64
|
||||
#define DAV1D_MAX_SEGMENTS 8
|
||||
#define DAV1D_NUM_REF_FRAMES 8
|
||||
#define DAV1D_PRIMARY_REF_NONE 7
|
||||
#define DAV1D_REFS_PER_FRAME 7
|
||||
#define DAV1D_TOTAL_REFS_PER_FRAME (DAV1D_REFS_PER_FRAME + 1)
|
||||
|
||||
enum Dav1dObuType {
|
||||
DAV1D_OBU_SEQ_HDR = 1,
|
||||
DAV1D_OBU_TD = 2,
|
||||
DAV1D_OBU_FRAME_HDR = 3,
|
||||
DAV1D_OBU_TILE_GRP = 4,
|
||||
DAV1D_OBU_METADATA = 5,
|
||||
DAV1D_OBU_FRAME = 6,
|
||||
DAV1D_OBU_REDUNDANT_FRAME_HDR = 7,
|
||||
DAV1D_OBU_PADDING = 15,
|
||||
};
|
||||
|
||||
enum Dav1dTxfmMode {
|
||||
DAV1D_TX_4X4_ONLY,
|
||||
DAV1D_TX_LARGEST,
|
||||
DAV1D_TX_SWITCHABLE,
|
||||
DAV1D_N_TX_MODES,
|
||||
};
|
||||
|
||||
enum Dav1dFilterMode {
|
||||
DAV1D_FILTER_8TAP_REGULAR,
|
||||
DAV1D_FILTER_8TAP_SMOOTH,
|
||||
DAV1D_FILTER_8TAP_SHARP,
|
||||
DAV1D_N_SWITCHABLE_FILTERS,
|
||||
DAV1D_FILTER_BILINEAR = DAV1D_N_SWITCHABLE_FILTERS,
|
||||
DAV1D_N_FILTERS,
|
||||
DAV1D_FILTER_SWITCHABLE = DAV1D_N_FILTERS,
|
||||
};
|
||||
|
||||
enum Dav1dAdaptiveBoolean {
|
||||
DAV1D_OFF = 0,
|
||||
DAV1D_ON = 1,
|
||||
DAV1D_ADAPTIVE = 2,
|
||||
};
|
||||
|
||||
enum Dav1dRestorationType {
|
||||
DAV1D_RESTORATION_NONE,
|
||||
DAV1D_RESTORATION_SWITCHABLE,
|
||||
DAV1D_RESTORATION_WIENER,
|
||||
DAV1D_RESTORATION_SGRPROJ,
|
||||
};
|
||||
|
||||
enum Dav1dWarpedMotionType {
|
||||
DAV1D_WM_TYPE_IDENTITY,
|
||||
DAV1D_WM_TYPE_TRANSLATION,
|
||||
DAV1D_WM_TYPE_ROT_ZOOM,
|
||||
DAV1D_WM_TYPE_AFFINE,
|
||||
};
|
||||
|
||||
typedef struct Dav1dWarpedMotionParams {
|
||||
enum Dav1dWarpedMotionType type;
|
||||
int32_t matrix[6];
|
||||
union {
|
||||
struct {
|
||||
int16_t alpha, beta, gamma, delta;
|
||||
} p;
|
||||
int16_t abcd[4];
|
||||
} u;
|
||||
} Dav1dWarpedMotionParams;
|
||||
|
||||
enum Dav1dPixelLayout {
|
||||
DAV1D_PIXEL_LAYOUT_I400, ///< monochrome
|
||||
DAV1D_PIXEL_LAYOUT_I420, ///< 4:2:0 planar
|
||||
DAV1D_PIXEL_LAYOUT_I422, ///< 4:2:2 planar
|
||||
DAV1D_PIXEL_LAYOUT_I444, ///< 4:4:4 planar
|
||||
};
|
||||
|
||||
enum Dav1dFrameType {
|
||||
DAV1D_FRAME_TYPE_KEY = 0, ///< Key Intra frame
|
||||
DAV1D_FRAME_TYPE_INTER = 1, ///< Inter frame
|
||||
DAV1D_FRAME_TYPE_INTRA = 2, ///< Non key Intra frame
|
||||
DAV1D_FRAME_TYPE_SWITCH = 3, ///< Switch Inter frame
|
||||
};
|
||||
|
||||
enum Dav1dColorPrimaries {
|
||||
DAV1D_COLOR_PRI_BT709 = 1,
|
||||
DAV1D_COLOR_PRI_UNKNOWN = 2,
|
||||
DAV1D_COLOR_PRI_BT470M = 4,
|
||||
DAV1D_COLOR_PRI_BT470BG = 5,
|
||||
DAV1D_COLOR_PRI_BT601 = 6,
|
||||
DAV1D_COLOR_PRI_SMPTE240 = 7,
|
||||
DAV1D_COLOR_PRI_FILM = 8,
|
||||
DAV1D_COLOR_PRI_BT2020 = 9,
|
||||
DAV1D_COLOR_PRI_XYZ = 10,
|
||||
DAV1D_COLOR_PRI_SMPTE431 = 11,
|
||||
DAV1D_COLOR_PRI_SMPTE432 = 12,
|
||||
DAV1D_COLOR_PRI_EBU3213 = 22,
|
||||
DAV1D_COLOR_PRI_RESERVED = 255,
|
||||
};
|
||||
|
||||
enum Dav1dTransferCharacteristics {
|
||||
DAV1D_TRC_BT709 = 1,
|
||||
DAV1D_TRC_UNKNOWN = 2,
|
||||
DAV1D_TRC_BT470M = 4,
|
||||
DAV1D_TRC_BT470BG = 5,
|
||||
DAV1D_TRC_BT601 = 6,
|
||||
DAV1D_TRC_SMPTE240 = 7,
|
||||
DAV1D_TRC_LINEAR = 8,
|
||||
DAV1D_TRC_LOG100 = 9, ///< logarithmic (100:1 range)
|
||||
DAV1D_TRC_LOG100_SQRT10 = 10, ///< lograithmic (100*sqrt(10):1 range)
|
||||
DAV1D_TRC_IEC61966 = 11,
|
||||
DAV1D_TRC_BT1361 = 12,
|
||||
DAV1D_TRC_SRGB = 13,
|
||||
DAV1D_TRC_BT2020_10BIT = 14,
|
||||
DAV1D_TRC_BT2020_12BIT = 15,
|
||||
DAV1D_TRC_SMPTE2084 = 16, ///< PQ
|
||||
DAV1D_TRC_SMPTE428 = 17,
|
||||
DAV1D_TRC_HLG = 18, ///< hybrid log/gamma (BT.2100 / ARIB STD-B67)
|
||||
DAV1D_TRC_RESERVED = 255,
|
||||
};
|
||||
|
||||
enum Dav1dMatrixCoefficients {
|
||||
DAV1D_MC_IDENTITY = 0,
|
||||
DAV1D_MC_BT709 = 1,
|
||||
DAV1D_MC_UNKNOWN = 2,
|
||||
DAV1D_MC_FCC = 4,
|
||||
DAV1D_MC_BT470BG = 5,
|
||||
DAV1D_MC_BT601 = 6,
|
||||
DAV1D_MC_SMPTE240 = 7,
|
||||
DAV1D_MC_SMPTE_YCGCO = 8,
|
||||
DAV1D_MC_BT2020_NCL = 9,
|
||||
DAV1D_MC_BT2020_CL = 10,
|
||||
DAV1D_MC_SMPTE2085 = 11,
|
||||
DAV1D_MC_CHROMAT_NCL = 12, ///< Chromaticity-derived
|
||||
DAV1D_MC_CHROMAT_CL = 13,
|
||||
DAV1D_MC_ICTCP = 14,
|
||||
DAV1D_MC_RESERVED = 255,
|
||||
};
|
||||
|
||||
enum Dav1dChromaSamplePosition {
|
||||
DAV1D_CHR_UNKNOWN = 0,
|
||||
DAV1D_CHR_VERTICAL = 1, ///< Horizontally co-located with luma(0, 0)
|
||||
///< sample, between two vertical samples
|
||||
DAV1D_CHR_COLOCATED = 2, ///< Co-located with luma(0, 0) sample
|
||||
};
|
||||
|
||||
typedef struct Dav1dContentLightLevel {
|
||||
uint16_t max_content_light_level;
|
||||
uint16_t max_frame_average_light_level;
|
||||
} Dav1dContentLightLevel;
|
||||
|
||||
typedef struct Dav1dMasteringDisplay {
|
||||
uint16_t primaries[3][2]; ///< 0.16 fixed point
|
||||
uint16_t white_point[2]; ///< 0.16 fixed point
|
||||
uint32_t max_luminance; ///< 24.8 fixed point
|
||||
uint32_t min_luminance; ///< 18.14 fixed point
|
||||
} Dav1dMasteringDisplay;
|
||||
|
||||
typedef struct Dav1dITUTT35 {
|
||||
uint8_t country_code;
|
||||
uint8_t country_code_extension_byte;
|
||||
size_t payload_size;
|
||||
uint8_t *payload;
|
||||
} Dav1dITUTT35;
|
||||
|
||||
typedef struct Dav1dSequenceHeader {
|
||||
/**
|
||||
* Stream profile, 0 for 8-10 bits/component 4:2:0 or monochrome;
|
||||
* 1 for 8-10 bits/component 4:4:4; 2 for 4:2:2 at any bits/component,
|
||||
* or 12 bits/component at any chroma subsampling.
|
||||
*/
|
||||
uint8_t profile;
|
||||
/**
|
||||
* Maximum dimensions for this stream. In non-scalable streams, these
|
||||
* are often the actual dimensions of the stream, although that is not
|
||||
* a normative requirement.
|
||||
*/
|
||||
int max_width, max_height;
|
||||
enum Dav1dPixelLayout layout; ///< format of the picture
|
||||
enum Dav1dColorPrimaries pri; ///< color primaries (av1)
|
||||
enum Dav1dTransferCharacteristics trc; ///< transfer characteristics (av1)
|
||||
enum Dav1dMatrixCoefficients mtrx; ///< matrix coefficients (av1)
|
||||
enum Dav1dChromaSamplePosition chr; ///< chroma sample position (av1)
|
||||
/**
|
||||
* 0, 1 and 2 mean 8, 10 or 12 bits/component, respectively. This is not
|
||||
* exactly the same as 'hbd' from the spec; the spec's hbd distinguishes
|
||||
* between 8 (0) and 10-12 (1) bits/component, and another element
|
||||
* (twelve_bit) to distinguish between 10 and 12 bits/component. To get
|
||||
* the spec's hbd, use !!our_hbd, and to get twelve_bit, use hbd == 2.
|
||||
*/
|
||||
uint8_t hbd;
|
||||
/**
|
||||
* Pixel data uses JPEG pixel range ([0,255] for 8bits) instead of
|
||||
* MPEG pixel range ([16,235] for 8bits luma, [16,240] for 8bits chroma).
|
||||
*/
|
||||
uint8_t color_range;
|
||||
|
||||
uint8_t num_operating_points;
|
||||
struct Dav1dSequenceHeaderOperatingPoint {
|
||||
uint8_t major_level, minor_level;
|
||||
uint8_t initial_display_delay;
|
||||
uint16_t idc;
|
||||
uint8_t tier;
|
||||
uint8_t decoder_model_param_present;
|
||||
uint8_t display_model_param_present;
|
||||
} operating_points[DAV1D_MAX_OPERATING_POINTS];
|
||||
|
||||
uint8_t still_picture;
|
||||
uint8_t reduced_still_picture_header;
|
||||
uint8_t timing_info_present;
|
||||
uint32_t num_units_in_tick;
|
||||
uint32_t time_scale;
|
||||
uint8_t equal_picture_interval;
|
||||
uint32_t num_ticks_per_picture;
|
||||
uint8_t decoder_model_info_present;
|
||||
uint8_t encoder_decoder_buffer_delay_length;
|
||||
uint32_t num_units_in_decoding_tick;
|
||||
uint8_t buffer_removal_delay_length;
|
||||
uint8_t frame_presentation_delay_length;
|
||||
uint8_t display_model_info_present;
|
||||
uint8_t width_n_bits, height_n_bits;
|
||||
uint8_t frame_id_numbers_present;
|
||||
uint8_t delta_frame_id_n_bits;
|
||||
uint8_t frame_id_n_bits;
|
||||
uint8_t sb128;
|
||||
uint8_t filter_intra;
|
||||
uint8_t intra_edge_filter;
|
||||
uint8_t inter_intra;
|
||||
uint8_t masked_compound;
|
||||
uint8_t warped_motion;
|
||||
uint8_t dual_filter;
|
||||
uint8_t order_hint;
|
||||
uint8_t jnt_comp;
|
||||
uint8_t ref_frame_mvs;
|
||||
enum Dav1dAdaptiveBoolean screen_content_tools;
|
||||
enum Dav1dAdaptiveBoolean force_integer_mv;
|
||||
uint8_t order_hint_n_bits;
|
||||
uint8_t super_res;
|
||||
uint8_t cdef;
|
||||
uint8_t restoration;
|
||||
uint8_t ss_hor, ss_ver, monochrome;
|
||||
uint8_t color_description_present;
|
||||
uint8_t separate_uv_delta_q;
|
||||
uint8_t film_grain_present;
|
||||
|
||||
// Dav1dSequenceHeaders of the same sequence are required to be
|
||||
// bit-identical until this offset. See 7.5 "Ordering of OBUs":
|
||||
// Within a particular coded video sequence, the contents of
|
||||
// sequence_header_obu must be bit-identical each time the
|
||||
// sequence header appears except for the contents of
|
||||
// operating_parameters_info.
|
||||
struct Dav1dSequenceHeaderOperatingParameterInfo {
|
||||
uint32_t decoder_buffer_delay;
|
||||
uint32_t encoder_buffer_delay;
|
||||
uint8_t low_delay_mode;
|
||||
} operating_parameter_info[DAV1D_MAX_OPERATING_POINTS];
|
||||
} Dav1dSequenceHeader;
|
||||
|
||||
typedef struct Dav1dSegmentationData {
|
||||
int16_t delta_q;
|
||||
int8_t delta_lf_y_v, delta_lf_y_h, delta_lf_u, delta_lf_v;
|
||||
int8_t ref;
|
||||
uint8_t skip;
|
||||
uint8_t globalmv;
|
||||
} Dav1dSegmentationData;
|
||||
|
||||
typedef struct Dav1dSegmentationDataSet {
|
||||
Dav1dSegmentationData d[DAV1D_MAX_SEGMENTS];
|
||||
uint8_t preskip;
|
||||
int8_t last_active_segid;
|
||||
} Dav1dSegmentationDataSet;
|
||||
|
||||
typedef struct Dav1dLoopfilterModeRefDeltas {
|
||||
int8_t mode_delta[2 /* is_zeromv */];
|
||||
int8_t ref_delta[DAV1D_TOTAL_REFS_PER_FRAME];
|
||||
} Dav1dLoopfilterModeRefDeltas;
|
||||
|
||||
typedef struct Dav1dFilmGrainData {
|
||||
unsigned seed;
|
||||
int num_y_points;
|
||||
uint8_t y_points[14][2 /* value, scaling */];
|
||||
int chroma_scaling_from_luma;
|
||||
int num_uv_points[2];
|
||||
uint8_t uv_points[2][10][2 /* value, scaling */];
|
||||
int scaling_shift;
|
||||
int ar_coeff_lag;
|
||||
int8_t ar_coeffs_y[24];
|
||||
int8_t ar_coeffs_uv[2][25 + 3 /* padding for alignment purposes */];
|
||||
uint64_t ar_coeff_shift;
|
||||
int grain_scale_shift;
|
||||
int uv_mult[2];
|
||||
int uv_luma_mult[2];
|
||||
int uv_offset[2];
|
||||
int overlap_flag;
|
||||
int clip_to_restricted_range;
|
||||
} Dav1dFilmGrainData;
|
||||
|
||||
typedef struct Dav1dFrameHeader {
|
||||
struct {
|
||||
Dav1dFilmGrainData data;
|
||||
uint8_t present, update;
|
||||
} film_grain; ///< film grain parameters
|
||||
enum Dav1dFrameType frame_type; ///< type of the picture
|
||||
int width[2 /* { coded_width, superresolution_upscaled_width } */], height;
|
||||
uint8_t frame_offset; ///< frame number
|
||||
uint8_t temporal_id; ///< temporal id of the frame for SVC
|
||||
uint8_t spatial_id; ///< spatial id of the frame for SVC
|
||||
|
||||
uint8_t show_existing_frame;
|
||||
uint8_t existing_frame_idx;
|
||||
uint32_t frame_id;
|
||||
uint32_t frame_presentation_delay;
|
||||
uint8_t show_frame;
|
||||
uint8_t showable_frame;
|
||||
uint8_t error_resilient_mode;
|
||||
uint8_t disable_cdf_update;
|
||||
uint8_t allow_screen_content_tools;
|
||||
uint8_t force_integer_mv;
|
||||
uint8_t frame_size_override;
|
||||
uint8_t primary_ref_frame;
|
||||
uint8_t buffer_removal_time_present;
|
||||
struct Dav1dFrameHeaderOperatingPoint {
|
||||
uint32_t buffer_removal_time;
|
||||
} operating_points[DAV1D_MAX_OPERATING_POINTS];
|
||||
uint8_t refresh_frame_flags;
|
||||
int render_width, render_height;
|
||||
struct {
|
||||
uint8_t width_scale_denominator;
|
||||
uint8_t enabled;
|
||||
} super_res;
|
||||
uint8_t have_render_size;
|
||||
uint8_t allow_intrabc;
|
||||
uint8_t frame_ref_short_signaling;
|
||||
int8_t refidx[DAV1D_REFS_PER_FRAME];
|
||||
uint8_t hp;
|
||||
enum Dav1dFilterMode subpel_filter_mode;
|
||||
uint8_t switchable_motion_mode;
|
||||
uint8_t use_ref_frame_mvs;
|
||||
uint8_t refresh_context;
|
||||
struct {
|
||||
uint8_t uniform;
|
||||
uint8_t n_bytes;
|
||||
uint8_t min_log2_cols, max_log2_cols, log2_cols, cols;
|
||||
uint8_t min_log2_rows, max_log2_rows, log2_rows, rows;
|
||||
uint16_t col_start_sb[DAV1D_MAX_TILE_COLS + 1];
|
||||
uint16_t row_start_sb[DAV1D_MAX_TILE_ROWS + 1];
|
||||
uint16_t update;
|
||||
} tiling;
|
||||
struct {
|
||||
uint8_t yac;
|
||||
int8_t ydc_delta;
|
||||
int8_t udc_delta, uac_delta, vdc_delta, vac_delta;
|
||||
uint8_t qm, qm_y, qm_u, qm_v;
|
||||
} quant;
|
||||
struct {
|
||||
uint8_t enabled, update_map, temporal, update_data;
|
||||
Dav1dSegmentationDataSet seg_data;
|
||||
uint8_t lossless[DAV1D_MAX_SEGMENTS], qidx[DAV1D_MAX_SEGMENTS];
|
||||
} segmentation;
|
||||
struct {
|
||||
struct {
|
||||
uint8_t present;
|
||||
uint8_t res_log2;
|
||||
} q;
|
||||
struct {
|
||||
uint8_t present;
|
||||
uint8_t res_log2;
|
||||
uint8_t multi;
|
||||
} lf;
|
||||
} delta;
|
||||
uint8_t all_lossless;
|
||||
struct {
|
||||
uint8_t level_y[2 /* dir */];
|
||||
uint8_t level_u, level_v;
|
||||
uint8_t mode_ref_delta_enabled;
|
||||
uint8_t mode_ref_delta_update;
|
||||
Dav1dLoopfilterModeRefDeltas mode_ref_deltas;
|
||||
uint8_t sharpness;
|
||||
} loopfilter;
|
||||
struct {
|
||||
uint8_t damping;
|
||||
uint8_t n_bits;
|
||||
uint8_t y_strength[DAV1D_MAX_CDEF_STRENGTHS];
|
||||
uint8_t uv_strength[DAV1D_MAX_CDEF_STRENGTHS];
|
||||
} cdef;
|
||||
struct {
|
||||
enum Dav1dRestorationType type[3 /* plane */];
|
||||
uint8_t unit_size[2 /* y, uv */];
|
||||
} restoration;
|
||||
enum Dav1dTxfmMode txfm_mode;
|
||||
uint8_t switchable_comp_refs;
|
||||
uint8_t skip_mode_allowed, skip_mode_enabled;
|
||||
int8_t skip_mode_refs[2];
|
||||
uint8_t warp_motion;
|
||||
uint8_t reduced_txtp_set;
|
||||
Dav1dWarpedMotionParams gmv[DAV1D_REFS_PER_FRAME];
|
||||
} Dav1dFrameHeader;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_HEADERS_H */
|
||||
36
media/libdav1d/src/include/dav1d/meson.build
Normal file
36
media/libdav1d/src/include/dav1d/meson.build
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Copyright © 2019, VideoLAN and dav1d authors
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
dav1d_api_headers = [
|
||||
'common.h',
|
||||
'data.h',
|
||||
'dav1d.h',
|
||||
'headers.h',
|
||||
'picture.h',
|
||||
'version.h',
|
||||
]
|
||||
|
||||
# install headers
|
||||
install_headers(dav1d_api_headers,
|
||||
subdir : 'dav1d')
|
||||
157
media/libdav1d/src/include/dav1d/picture.h
Normal file
157
media/libdav1d/src/include/dav1d/picture.h
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright © 2018-2020, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Two Orioles, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_PICTURE_H
|
||||
#define DAV1D_PICTURE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "headers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Number of bytes to align AND pad picture memory buffers by, so that SIMD
|
||||
* implementations can over-read by a few bytes, and use aligned read/write
|
||||
* instructions. */
|
||||
#define DAV1D_PICTURE_ALIGNMENT 64
|
||||
|
||||
typedef struct Dav1dPictureParameters {
|
||||
int w; ///< width (in pixels)
|
||||
int h; ///< height (in pixels)
|
||||
enum Dav1dPixelLayout layout; ///< format of the picture
|
||||
int bpc; ///< bits per pixel component (8 or 10)
|
||||
} Dav1dPictureParameters;
|
||||
|
||||
typedef struct Dav1dPicture {
|
||||
Dav1dSequenceHeader *seq_hdr;
|
||||
Dav1dFrameHeader *frame_hdr;
|
||||
|
||||
/**
|
||||
* Pointers to planar image data (Y is [0], U is [1], V is [2]). The data
|
||||
* should be bytes (for 8 bpc) or words (for 10 bpc). In case of words
|
||||
* containing 10 bpc image data, the pixels should be located in the LSB
|
||||
* bits, so that values range between [0, 1023]; the upper bits should be
|
||||
* zero'ed out.
|
||||
*/
|
||||
void *data[3];
|
||||
|
||||
/**
|
||||
* Number of bytes between 2 lines in data[] for luma [0] or chroma [1].
|
||||
*/
|
||||
ptrdiff_t stride[2];
|
||||
|
||||
Dav1dPictureParameters p;
|
||||
Dav1dDataProps m;
|
||||
|
||||
/**
|
||||
* High Dynamic Range Content Light Level metadata applying to this picture,
|
||||
* as defined in section 5.8.3 and 6.7.3
|
||||
*/
|
||||
Dav1dContentLightLevel *content_light;
|
||||
/**
|
||||
* High Dynamic Range Mastering Display Color Volume metadata applying to
|
||||
* this picture, as defined in section 5.8.4 and 6.7.4
|
||||
*/
|
||||
Dav1dMasteringDisplay *mastering_display;
|
||||
/**
|
||||
* Array of ITU-T T.35 metadata as defined in section 5.8.2 and 6.7.2
|
||||
*/
|
||||
Dav1dITUTT35 *itut_t35;
|
||||
|
||||
/**
|
||||
* Number of ITU-T T35 metadata entries in the array
|
||||
*/
|
||||
size_t n_itut_t35;
|
||||
|
||||
uintptr_t reserved[4]; ///< reserved for future use
|
||||
|
||||
struct Dav1dRef *frame_hdr_ref; ///< Dav1dFrameHeader allocation origin
|
||||
struct Dav1dRef *seq_hdr_ref; ///< Dav1dSequenceHeader allocation origin
|
||||
struct Dav1dRef *content_light_ref; ///< Dav1dContentLightLevel allocation origin
|
||||
struct Dav1dRef *mastering_display_ref; ///< Dav1dMasteringDisplay allocation origin
|
||||
struct Dav1dRef *itut_t35_ref; ///< Dav1dITUTT35 allocation origin
|
||||
uintptr_t reserved_ref[4]; ///< reserved for future use
|
||||
struct Dav1dRef *ref; ///< Frame data allocation origin
|
||||
|
||||
void *allocator_data; ///< pointer managed by the allocator
|
||||
} Dav1dPicture;
|
||||
|
||||
typedef struct Dav1dPicAllocator {
|
||||
void *cookie; ///< custom data to pass to the allocator callbacks.
|
||||
/**
|
||||
* Allocate the picture buffer based on the Dav1dPictureParameters.
|
||||
*
|
||||
* The data[0], data[1] and data[2] must be DAV1D_PICTURE_ALIGNMENT byte
|
||||
* aligned and with a pixel width/height multiple of 128 pixels. Any
|
||||
* allocated memory area should also be padded by DAV1D_PICTURE_ALIGNMENT
|
||||
* bytes.
|
||||
* data[1] and data[2] must share the same stride[1].
|
||||
*
|
||||
* This function will be called on the main thread (the thread which calls
|
||||
* dav1d_get_picture()).
|
||||
*
|
||||
* @param pic The picture to allocate the buffer for. The callback needs to
|
||||
* fill the picture data[0], data[1], data[2], stride[0] and
|
||||
* stride[1].
|
||||
* The allocator can fill the pic allocator_data pointer with
|
||||
* a custom pointer that will be passed to
|
||||
* release_picture_callback().
|
||||
* @param cookie Custom pointer passed to all calls.
|
||||
*
|
||||
* @note No fields other than data, stride and allocator_data must be filled
|
||||
* by this callback.
|
||||
* @return 0 on success. A negative DAV1D_ERR value on error.
|
||||
*/
|
||||
int (*alloc_picture_callback)(Dav1dPicture *pic, void *cookie);
|
||||
/**
|
||||
* Release the picture buffer.
|
||||
*
|
||||
* If frame threading is used, this function may be called by the main
|
||||
* thread (the thread which calls dav1d_get_picture()) or any of the frame
|
||||
* threads and thus must be thread-safe. If frame threading is not used,
|
||||
* this function will only be called on the main thread.
|
||||
*
|
||||
* @param pic The picture that was filled by alloc_picture_callback().
|
||||
* @param cookie Custom pointer passed to all calls.
|
||||
*/
|
||||
void (*release_picture_callback)(Dav1dPicture *pic, void *cookie);
|
||||
} Dav1dPicAllocator;
|
||||
|
||||
/**
|
||||
* Release reference to a picture.
|
||||
*/
|
||||
DAV1D_API void dav1d_picture_unref(Dav1dPicture *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_PICTURE_H */
|
||||
50
media/libdav1d/src/include/dav1d/version.h
Normal file
50
media/libdav1d/src/include/dav1d/version.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright © 2019-2024, VideoLAN and dav1d authors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef DAV1D_VERSION_H
|
||||
#define DAV1D_VERSION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DAV1D_API_VERSION_MAJOR 7
|
||||
#define DAV1D_API_VERSION_MINOR 0
|
||||
#define DAV1D_API_VERSION_PATCH 0
|
||||
|
||||
/**
|
||||
* Extract version components from the value returned by
|
||||
* dav1d_version_int()
|
||||
*/
|
||||
#define DAV1D_API_MAJOR(v) (((v) >> 16) & 0xFF)
|
||||
#define DAV1D_API_MINOR(v) (((v) >> 8) & 0xFF)
|
||||
#define DAV1D_API_PATCH(v) (((v) >> 0) & 0xFF)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* DAV1D_VERSION_H */
|
||||
34
media/libdav1d/src/include/meson.build
Normal file
34
media/libdav1d/src/include/meson.build
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Copyright © 2018, VideoLAN and dav1d authors
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# Revision file (vcs_version.h) generation
|
||||
dav1d_git_dir = join_paths(dav1d_src_root, '.git')
|
||||
rev_target = vcs_tag(command: [
|
||||
'git', '--git-dir', dav1d_git_dir, 'describe', '--long', '--always'
|
||||
],
|
||||
input: 'vcs_version.h.in',
|
||||
output: 'vcs_version.h'
|
||||
)
|
||||
|
||||
subdir('dav1d')
|
||||
2
media/libdav1d/src/include/vcs_version.h.in
Normal file
2
media/libdav1d/src/include/vcs_version.h.in
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/* auto-generated, do not edit */
|
||||
#define DAV1D_VERSION "@VCS_TAG@"
|
||||
610
media/libdav1d/src/meson.build
Normal file
610
media/libdav1d/src/meson.build
Normal file
|
|
@ -0,0 +1,610 @@
|
|||
# Copyright © 2018-2024, VideoLAN and dav1d authors
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
project('dav1d', ['c'],
|
||||
version: '1.5.3',
|
||||
default_options: ['c_std=c99',
|
||||
'warning_level=2',
|
||||
'buildtype=release',
|
||||
'b_ndebug=if-release'],
|
||||
meson_version: '>= 0.49.0')
|
||||
|
||||
dav1d_src_root = meson.current_source_dir()
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
# Configuratin data for config.h
|
||||
cdata = configuration_data()
|
||||
|
||||
# Configuration data for config.asm
|
||||
cdata_asm = configuration_data()
|
||||
|
||||
# Include directories
|
||||
dav1d_inc_dirs = include_directories(['.', 'include/dav1d', 'include'])
|
||||
|
||||
dav1d_api_version_major = cc.get_define('DAV1D_API_VERSION_MAJOR',
|
||||
prefix: '#include "dav1d/version.h"',
|
||||
include_directories: dav1d_inc_dirs).strip()
|
||||
dav1d_api_version_minor = cc.get_define('DAV1D_API_VERSION_MINOR',
|
||||
prefix: '#include "dav1d/version.h"',
|
||||
include_directories: dav1d_inc_dirs).strip()
|
||||
dav1d_api_version_revision = cc.get_define('DAV1D_API_VERSION_PATCH',
|
||||
prefix: '#include "dav1d/version.h"',
|
||||
include_directories: dav1d_inc_dirs).strip()
|
||||
dav1d_soname_version = '@0@.@1@.@2@'.format(dav1d_api_version_major,
|
||||
dav1d_api_version_minor,
|
||||
dav1d_api_version_revision)
|
||||
|
||||
#
|
||||
# Option handling
|
||||
#
|
||||
|
||||
# Bitdepth option
|
||||
dav1d_bitdepths = get_option('bitdepths')
|
||||
foreach bitdepth : ['8', '16']
|
||||
cdata.set10('CONFIG_@0@BPC'.format(bitdepth), dav1d_bitdepths.contains(bitdepth))
|
||||
endforeach
|
||||
|
||||
# ASM option
|
||||
is_asm_enabled = (get_option('enable_asm') == true and
|
||||
(host_machine.cpu_family() == 'aarch64' or
|
||||
host_machine.cpu_family().startswith('arm') or
|
||||
host_machine.cpu() == 'ppc64le' or
|
||||
host_machine.cpu_family().startswith('riscv') or
|
||||
host_machine.cpu_family().startswith('loongarch') or
|
||||
host_machine.cpu_family() == 'x86' or
|
||||
(host_machine.cpu_family() == 'x86_64' and cc.get_define('__ILP32__').strip() == '')))
|
||||
cdata.set10('HAVE_ASM', is_asm_enabled)
|
||||
|
||||
if is_asm_enabled and get_option('b_sanitize') == 'memory'
|
||||
error('asm causes false positive with memory sanitizer. Use \'-Denable_asm=false\'.')
|
||||
endif
|
||||
|
||||
cdata.set10('TRIM_DSP_FUNCTIONS', get_option('trim_dsp') == 'true' or
|
||||
(get_option('trim_dsp') == 'if-release' and get_option('buildtype') == 'release'))
|
||||
|
||||
# Logging option
|
||||
cdata.set10('CONFIG_LOG', get_option('logging'))
|
||||
|
||||
cdata.set10('CONFIG_MACOS_KPERF', get_option('macos_kperf'))
|
||||
|
||||
#
|
||||
# OS/Compiler checks and defines
|
||||
#
|
||||
|
||||
# Arguments in test_args will be used even on feature tests
|
||||
test_args = []
|
||||
|
||||
optional_arguments = []
|
||||
optional_link_arguments = []
|
||||
|
||||
if host_machine.system() in ['linux', 'gnu', 'emscripten']
|
||||
test_args += '-D_GNU_SOURCE'
|
||||
add_project_arguments('-D_GNU_SOURCE', language: 'c')
|
||||
endif
|
||||
|
||||
have_clock_gettime = false
|
||||
have_posix_memalign = false
|
||||
have_memalign = false
|
||||
have_aligned_alloc = false
|
||||
if host_machine.system() == 'windows'
|
||||
cdata.set('_WIN32_WINNT', '0x0601')
|
||||
cdata.set('UNICODE', 1) # Define to 1 for Unicode (Wide Chars) APIs
|
||||
cdata.set('_UNICODE', 1) # Define to 1 for Unicode (Wide Chars) APIs
|
||||
cdata.set('__USE_MINGW_ANSI_STDIO', 1) # Define to force use of MinGW printf
|
||||
cdata.set('_CRT_DECLARE_NONSTDC_NAMES', 1) # Define to get off_t from sys/types.h on MSVC
|
||||
if cc.has_function('fseeko', prefix : '#include <stdio.h>', args : test_args)
|
||||
cdata.set('_FILE_OFFSET_BITS', 64) # Not set by default by Meson on Windows
|
||||
else
|
||||
cdata.set('fseeko', '_fseeki64')
|
||||
cdata.set('ftello', '_ftelli64')
|
||||
endif
|
||||
|
||||
if host_machine.cpu_family() == 'x86_64'
|
||||
if cc.get_argument_syntax() != 'msvc'
|
||||
optional_link_arguments += '-Wl,--dynamicbase,--nxcompat,--tsaware,--high-entropy-va'
|
||||
endif
|
||||
elif host_machine.cpu_family() == 'x86' or host_machine.cpu_family() == 'arm'
|
||||
if cc.get_argument_syntax() == 'msvc'
|
||||
optional_link_arguments += '/largeaddressaware'
|
||||
else
|
||||
optional_link_arguments += '-Wl,--dynamicbase,--nxcompat,--tsaware,--large-address-aware'
|
||||
endif
|
||||
endif
|
||||
|
||||
# On Windows, we use a compatibility layer to emulate pthread
|
||||
thread_dependency = []
|
||||
thread_compat_dep = declare_dependency(sources : files('src/win32/thread.c'))
|
||||
|
||||
rt_dependency = []
|
||||
|
||||
rc_version_array = meson.project_version().split('.')
|
||||
winmod = import('windows')
|
||||
rc_data = configuration_data()
|
||||
rc_data.set('PROJECT_VERSION_MAJOR', rc_version_array[0])
|
||||
rc_data.set('PROJECT_VERSION_MINOR', rc_version_array[1])
|
||||
rc_data.set('PROJECT_VERSION_REVISION', rc_version_array[2])
|
||||
rc_data.set('API_VERSION_MAJOR', dav1d_api_version_major)
|
||||
rc_data.set('API_VERSION_MINOR', dav1d_api_version_minor)
|
||||
rc_data.set('API_VERSION_REVISION', dav1d_api_version_revision)
|
||||
rc_data.set('COPYRIGHT_YEARS', '2018-2025')
|
||||
else
|
||||
thread_dependency = dependency('threads')
|
||||
thread_compat_dep = []
|
||||
|
||||
rt_dependency = []
|
||||
if cc.has_function('clock_gettime', prefix : '#include <time.h>', args : test_args)
|
||||
have_clock_gettime = true
|
||||
elif host_machine.system() not in ['darwin', 'ios', 'tvos']
|
||||
rt_dependency = cc.find_library('rt', required: false)
|
||||
if not cc.has_function('clock_gettime', prefix : '#include <time.h>', args : test_args, dependencies : rt_dependency)
|
||||
error('clock_gettime not found')
|
||||
endif
|
||||
have_clock_gettime = true
|
||||
endif
|
||||
|
||||
have_posix_memalign = cc.has_function('posix_memalign', prefix : '#include <stdlib.h>', args : test_args)
|
||||
have_memalign = cc.has_function('memalign', prefix : '#include <malloc.h>', args : test_args)
|
||||
have_aligned_alloc = cc.has_function('aligned_alloc', prefix : '#include <stdlib.h>', args : test_args)
|
||||
endif
|
||||
|
||||
cdata.set10('HAVE_CLOCK_GETTIME', have_clock_gettime)
|
||||
cdata.set10('HAVE_POSIX_MEMALIGN', have_posix_memalign)
|
||||
cdata.set10('HAVE_MEMALIGN', have_memalign)
|
||||
cdata.set10('HAVE_ALIGNED_ALLOC', have_aligned_alloc)
|
||||
|
||||
# check for fseeko on android. It is not always available if _FILE_OFFSET_BITS is defined to 64
|
||||
have_fseeko = true
|
||||
if host_machine.system() == 'android'
|
||||
if not cc.has_function('fseeko', prefix : '#include <stdio.h>', args : test_args)
|
||||
if cc.has_function('fseeko', prefix : '#include <stdio.h>', args : test_args + ['-U_FILE_OFFSET_BITS'])
|
||||
warning('Files larger than 2 gigabytes might not be supported in the dav1d CLI tool.')
|
||||
add_project_arguments('-U_FILE_OFFSET_BITS', language: 'c')
|
||||
elif get_option('enable_tools')
|
||||
error('dav1d CLI tool needs fseeko()')
|
||||
else
|
||||
have_fseeko = false
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
libdl_dependency = []
|
||||
have_dlsym = false
|
||||
if host_machine.system() == 'linux'
|
||||
libdl_dependency = cc.find_library('dl', required : false)
|
||||
have_dlsym = cc.has_function('dlsym', prefix : '#include <dlfcn.h>', args : test_args, dependencies : libdl_dependency)
|
||||
endif
|
||||
cdata.set10('HAVE_DLSYM', have_dlsym)
|
||||
|
||||
libm_dependency = cc.find_library('m', required: false)
|
||||
|
||||
|
||||
# Header checks
|
||||
|
||||
stdatomic_dependencies = []
|
||||
if not cc.check_header('stdatomic.h')
|
||||
if cc.get_id() == 'msvc'
|
||||
# we have a custom replacement for MSVC
|
||||
stdatomic_dependencies += declare_dependency(
|
||||
include_directories : include_directories('include/compat/msvc'),
|
||||
)
|
||||
elif cc.compiles('''int main() { int v = 0; return __atomic_fetch_add(&v, 1, __ATOMIC_SEQ_CST); }''',
|
||||
name : 'GCC-style atomics', args : test_args)
|
||||
stdatomic_dependencies += declare_dependency(
|
||||
include_directories : include_directories('include/compat/gcc'),
|
||||
)
|
||||
else
|
||||
error('Atomics not supported')
|
||||
endif
|
||||
endif
|
||||
|
||||
if host_machine.cpu_family().startswith('wasm')
|
||||
# enable atomics + bulk-memory features
|
||||
stdatomic_dependencies += thread_dependency.partial_dependency(compile_args: true)
|
||||
endif
|
||||
|
||||
cdata.set10('HAVE_SYS_TYPES_H', cc.check_header('sys/types.h'))
|
||||
cdata.set10('HAVE_UNISTD_H', cc.check_header('unistd.h'))
|
||||
cdata.set10('HAVE_IO_H', cc.check_header('io.h'))
|
||||
|
||||
have_pthread_np = cc.check_header('pthread_np.h')
|
||||
cdata.set10('HAVE_PTHREAD_NP_H', have_pthread_np)
|
||||
test_args += '-DHAVE_PTHREAD_NP_H=' + (have_pthread_np ? '1' : '0')
|
||||
|
||||
# Function checks
|
||||
|
||||
if not cc.has_function('getopt_long', prefix : '#include <getopt.h>', args : test_args)
|
||||
getopt_dependency = declare_dependency(
|
||||
sources: files('tools/compat/getopt.c'),
|
||||
include_directories : include_directories('include/compat'),
|
||||
)
|
||||
else
|
||||
getopt_dependency = []
|
||||
endif
|
||||
|
||||
have_getauxval = false
|
||||
have_elf_aux_info = false
|
||||
if (host_machine.cpu_family() == 'aarch64' or
|
||||
host_machine.cpu_family().startswith('arm') or
|
||||
host_machine.cpu_family().startswith('loongarch') or
|
||||
host_machine.cpu() == 'ppc64le' or
|
||||
host_machine.cpu_family().startswith('riscv'))
|
||||
have_getauxval = cc.has_function('getauxval', prefix : '#include <sys/auxv.h>', args : test_args)
|
||||
have_elf_aux_info = cc.has_function('elf_aux_info', prefix : '#include <sys/auxv.h>', args : test_args)
|
||||
endif
|
||||
|
||||
cdata.set10('HAVE_GETAUXVAL', have_getauxval)
|
||||
cdata.set10('HAVE_ELF_AUX_INFO', have_elf_aux_info)
|
||||
|
||||
pthread_np_prefix = '''
|
||||
#include <pthread.h>
|
||||
#if HAVE_PTHREAD_NP_H
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
'''
|
||||
cdata.set10('HAVE_PTHREAD_GETAFFINITY_NP', cc.has_function('pthread_getaffinity_np', prefix : pthread_np_prefix, args : test_args, dependencies : thread_dependency))
|
||||
cdata.set10('HAVE_PTHREAD_SETAFFINITY_NP', cc.has_function('pthread_setaffinity_np', prefix : pthread_np_prefix, args : test_args, dependencies : thread_dependency))
|
||||
cdata.set10('HAVE_PTHREAD_SETNAME_NP', cc.has_function('pthread_setname_np', prefix : pthread_np_prefix, args : test_args, dependencies : thread_dependency))
|
||||
cdata.set10('HAVE_PTHREAD_SET_NAME_NP', cc.has_function('pthread_set_name_np', prefix : pthread_np_prefix, args : test_args, dependencies : thread_dependency))
|
||||
|
||||
cdata.set10('HAVE_C11_GENERIC', cc.compiles('int x = _Generic(0, default: 0);', name: '_Generic', args: test_args))
|
||||
|
||||
# Compiler flag tests
|
||||
|
||||
if cc.has_argument('-fvisibility=hidden')
|
||||
add_project_arguments('-fvisibility=hidden', language: 'c')
|
||||
else
|
||||
warning('Compiler does not support -fvisibility=hidden, all symbols will be public!')
|
||||
endif
|
||||
|
||||
# Compiler flags that should be set
|
||||
# But when the compiler does not supports them
|
||||
# it is not an error and silently tolerated
|
||||
if cc.get_argument_syntax() != 'msvc'
|
||||
optional_arguments += [
|
||||
'-Wundef',
|
||||
'-Werror=vla',
|
||||
'-Wno-maybe-uninitialized',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wstrict-prototypes',
|
||||
'-Werror=missing-prototypes',
|
||||
'-Wshorten-64-to-32',
|
||||
]
|
||||
if host_machine.cpu_family() == 'x86'
|
||||
optional_arguments += [
|
||||
'-msse2',
|
||||
'-mfpmath=sse',
|
||||
]
|
||||
endif
|
||||
else
|
||||
optional_arguments += [
|
||||
'-wd4028', # parameter different from declaration
|
||||
'-wd4090', # broken with arrays of pointers
|
||||
'-wd4996' # use of POSIX functions
|
||||
]
|
||||
endif
|
||||
|
||||
if (get_option('buildtype') != 'debug' and get_option('buildtype') != 'plain')
|
||||
optional_arguments += '-fomit-frame-pointer'
|
||||
optional_arguments += '-ffast-math'
|
||||
endif
|
||||
|
||||
if (host_machine.system() in ['darwin', 'ios', 'tvos'] and cc.get_id() == 'clang' and
|
||||
cc.version().startswith('11'))
|
||||
# Workaround for Xcode 11 -fstack-check bug, see #301
|
||||
optional_arguments += '-fno-stack-check'
|
||||
endif
|
||||
|
||||
if (host_machine.cpu_family() == 'aarch64' or host_machine.cpu_family().startswith('arm'))
|
||||
optional_arguments += '-fno-align-functions'
|
||||
endif
|
||||
|
||||
add_project_arguments(cc.get_supported_arguments(optional_arguments), language : 'c')
|
||||
add_project_link_arguments(cc.get_supported_link_arguments(optional_link_arguments), language : 'c')
|
||||
|
||||
# libFuzzer related things
|
||||
fuzzing_engine = get_option('fuzzing_engine')
|
||||
if fuzzing_engine == 'libfuzzer'
|
||||
if not cc.has_argument('-fsanitize=fuzzer')
|
||||
error('fuzzing_engine libfuzzer requires "-fsanitize=fuzzer"')
|
||||
endif
|
||||
fuzzer_args = ['-fsanitize=fuzzer-no-link', '-fsanitize=fuzzer']
|
||||
add_project_arguments(cc.first_supported_argument(fuzzer_args), language : 'c')
|
||||
endif
|
||||
|
||||
cdata.set10('ENDIANNESS_BIG', host_machine.endian() == 'big')
|
||||
|
||||
if host_machine.cpu_family().startswith('x86')
|
||||
if get_option('stack_alignment') > 0
|
||||
stack_alignment = get_option('stack_alignment')
|
||||
elif host_machine.cpu_family() == 'x86_64' or host_machine.system() in ['linux', 'darwin', 'ios', 'tvos']
|
||||
stack_alignment = 16
|
||||
else
|
||||
stack_alignment = 4
|
||||
endif
|
||||
cdata_asm.set('STACK_ALIGNMENT', stack_alignment)
|
||||
endif
|
||||
|
||||
#
|
||||
# ASM specific stuff
|
||||
#
|
||||
|
||||
use_gaspp = false
|
||||
if (is_asm_enabled and
|
||||
(host_machine.cpu_family() == 'aarch64' or
|
||||
host_machine.cpu_family().startswith('arm')) and
|
||||
cc.get_argument_syntax() == 'msvc' and
|
||||
(cc.get_id() != 'clang-cl' or meson.version().version_compare('<0.58.0')))
|
||||
gaspp = find_program('gas-preprocessor.pl')
|
||||
use_gaspp = true
|
||||
gaspp_args = [
|
||||
'-as-type', 'armasm',
|
||||
'-arch', host_machine.cpu_family(),
|
||||
'--',
|
||||
host_machine.cpu_family() == 'aarch64' ? 'armasm64' : 'armasm',
|
||||
'-nologo',
|
||||
'-I@0@'.format(dav1d_src_root),
|
||||
'-I@0@/'.format(meson.current_build_dir()),
|
||||
]
|
||||
gaspp_gen = generator(gaspp,
|
||||
output: '@BASENAME@.obj',
|
||||
arguments: gaspp_args + [
|
||||
'@INPUT@',
|
||||
'-c',
|
||||
'-o', '@OUTPUT@'
|
||||
])
|
||||
endif
|
||||
|
||||
cdata.set10('ARCH_AARCH64', host_machine.cpu_family() == 'aarch64' or host_machine.cpu() == 'arm64')
|
||||
cdata.set10('ARCH_ARM', host_machine.cpu_family().startswith('arm') and host_machine.cpu() != 'arm64')
|
||||
|
||||
have_as_func = false
|
||||
have_as_arch = false
|
||||
aarch64_extensions = {
|
||||
'dotprod': 'udot v0.4s, v0.16b, v0.16b',
|
||||
'i8mm': 'usdot v0.4s, v0.16b, v0.16b',
|
||||
'sve': 'whilelt p0.s, x0, x1',
|
||||
'sve2': 'sqrdmulh z0.s, z0.s, z0.s',
|
||||
}
|
||||
supported_aarch64_archexts = []
|
||||
supported_aarch64_instructions = []
|
||||
if (is_asm_enabled and
|
||||
(host_machine.cpu_family() == 'aarch64' or
|
||||
host_machine.cpu_family().startswith('arm')))
|
||||
|
||||
as_func_code = '''__asm__ (
|
||||
".func meson_test"
|
||||
".endfunc"
|
||||
);
|
||||
'''
|
||||
have_as_func = cc.compiles(as_func_code)
|
||||
|
||||
# fedora package build infrastructure uses a gcc specs file to enable
|
||||
# '-fPIE' by default. The chosen way only adds '-fPIE' to the C compiler
|
||||
# with integrated preprocessor. It is not added to the standalone
|
||||
# preprocessor or the preprocessing stage of '.S' files. So we have to
|
||||
# compile code to check if we have to define PIC for the arm asm to
|
||||
# avoid absolute relocations when building for example checkasm.
|
||||
check_pic_code = '''
|
||||
#if defined(PIC)
|
||||
#error "PIC already defined"
|
||||
#elif !(defined(__PIC__) || defined(__pic__))
|
||||
#error "no pic"
|
||||
#endif
|
||||
'''
|
||||
if cc.compiles(check_pic_code)
|
||||
cdata.set('PIC', '3')
|
||||
endif
|
||||
|
||||
if host_machine.cpu_family() == 'aarch64'
|
||||
have_as_arch = cc.compiles('''__asm__ (".arch armv8-a");''')
|
||||
as_arch_str = ''
|
||||
if have_as_arch
|
||||
as_arch_level = 'armv8-a'
|
||||
# Check what .arch levels are supported. In principle, we only
|
||||
# want to detect up to armv8.2-a here (binutils requires that
|
||||
# in order to enable i8mm). However, older Clang versions
|
||||
# (before Clang 17, and Xcode versions up to and including 15.0)
|
||||
# didn't support controlling dotprod/i8mm extensions via
|
||||
# .arch_extension, therefore try to enable a high enough .arch
|
||||
# level as well, to implicitly make them available via that.
|
||||
foreach arch : ['armv8.2-a', 'armv8.4-a', 'armv8.6-a']
|
||||
if cc.compiles('__asm__ (".arch ' + arch + '\\n");')
|
||||
as_arch_level = arch
|
||||
endif
|
||||
endforeach
|
||||
# Clang versions before 17 also had a bug
|
||||
# (https://github.com/llvm/llvm-project/issues/32220)
|
||||
# causing a plain ".arch <level>" to not have any effect unless it
|
||||
# had an extra "+<feature>" included - but it was activated on the
|
||||
# next ".arch_extension" directive instead. Check if we can include
|
||||
# "+crc" as dummy feature to make the .arch directive behave as
|
||||
# expected and take effect right away.
|
||||
if cc.compiles('__asm__ (".arch ' + as_arch_level + '+crc\\n");')
|
||||
as_arch_level = as_arch_level + '+crc'
|
||||
endif
|
||||
cdata.set('AS_ARCH_LEVEL', as_arch_level)
|
||||
as_arch_str = '".arch ' + as_arch_level + '\\n"'
|
||||
endif
|
||||
if use_gaspp
|
||||
python3 = import('python').find_installation()
|
||||
endif
|
||||
foreach name, instr : aarch64_extensions
|
||||
if use_gaspp
|
||||
f = configure_file(
|
||||
command: [python3, '-c', 'import sys; print(sys.argv[1])', '@0@'.format(instr)],
|
||||
output: 'test-@0@.S'.format(name),
|
||||
capture: true)
|
||||
r = run_command(gaspp, gaspp_args, f, '-c', '-o', meson.current_build_dir() / 'test-' + name + '.obj', check: false)
|
||||
message('Checking for gaspp/armasm64 ' + name.to_upper() + ': ' + (r.returncode() == 0 ? 'YES' : 'NO'))
|
||||
if r.returncode() == 0
|
||||
supported_aarch64_instructions += name
|
||||
endif
|
||||
else
|
||||
# Test for support for the various extensions. First test if
|
||||
# the assembler supports the .arch_extension directive for
|
||||
# enabling/disabling the extension, then separately check whether
|
||||
# the instructions themselves are supported. Even if .arch_extension
|
||||
# isn't supported, we may be able to assemble the instructions
|
||||
# if the .arch level includes support for them.
|
||||
code = '__asm__ (' + as_arch_str
|
||||
code += '".arch_extension ' + name + '\\n"'
|
||||
code += ');'
|
||||
supports_archext = cc.compiles(code)
|
||||
code = '__asm__ (' + as_arch_str
|
||||
if supports_archext
|
||||
supported_aarch64_archexts += name
|
||||
code += '".arch_extension ' + name + '\\n"'
|
||||
endif
|
||||
code += '"' + instr + '\\n"'
|
||||
code += ');'
|
||||
if cc.compiles(code, name: name.to_upper())
|
||||
supported_aarch64_instructions += name
|
||||
endif
|
||||
endif
|
||||
endforeach
|
||||
endif
|
||||
endif
|
||||
|
||||
cdata.set10('HAVE_AS_FUNC', have_as_func)
|
||||
cdata.set10('HAVE_AS_ARCH_DIRECTIVE', have_as_arch)
|
||||
foreach name, _ : aarch64_extensions
|
||||
cdata.set10('HAVE_AS_ARCHEXT_' + name.to_upper() + '_DIRECTIVE', name in supported_aarch64_archexts)
|
||||
cdata.set10('HAVE_' + name.to_upper(), name in supported_aarch64_instructions)
|
||||
endforeach
|
||||
|
||||
cdata.set10('ARCH_X86', host_machine.cpu_family().startswith('x86'))
|
||||
cdata.set10('ARCH_X86_64', host_machine.cpu_family() == 'x86_64')
|
||||
cdata.set10('ARCH_X86_32', host_machine.cpu_family() == 'x86')
|
||||
|
||||
if host_machine.cpu_family().startswith('x86')
|
||||
cdata_asm.set('private_prefix', 'dav1d')
|
||||
cdata_asm.set10('ARCH_X86_64', host_machine.cpu_family() == 'x86_64')
|
||||
cdata_asm.set10('ARCH_X86_32', host_machine.cpu_family() == 'x86')
|
||||
cdata_asm.set10('PIC', true)
|
||||
|
||||
# Convert SSE asm into (128-bit) AVX when compiler flags are set to use AVX instructions
|
||||
cdata_asm.set10('FORCE_VEX_ENCODING', cc.get_define('__AVX__').strip() != '')
|
||||
endif
|
||||
|
||||
cdata.set10('ARCH_PPC64LE', host_machine.cpu() == 'ppc64le')
|
||||
|
||||
cdata.set10('ARCH_RISCV', host_machine.cpu_family().startswith('riscv'))
|
||||
cdata.set10('ARCH_RV32', host_machine.cpu_family() == 'riscv32')
|
||||
cdata.set10('ARCH_RV64', host_machine.cpu_family() == 'riscv64')
|
||||
|
||||
cdata.set10('ARCH_LOONGARCH', host_machine.cpu_family().startswith('loongarch'))
|
||||
cdata.set10('ARCH_LOONGARCH32', host_machine.cpu_family() == 'loongarch32')
|
||||
cdata.set10('ARCH_LOONGARCH64', host_machine.cpu_family() == 'loongarch64')
|
||||
|
||||
# meson's cc.symbols_have_underscore_prefix() is unfortunately unrelieably
|
||||
# when additional flags like '-fprofile-instr-generate' are passed via CFLAGS
|
||||
# see following meson issue https://github.com/mesonbuild/meson/issues/5482
|
||||
if (host_machine.system() in ['darwin', 'ios', 'tvos'] or
|
||||
(host_machine.system() == 'windows' and host_machine.cpu_family() == 'x86'))
|
||||
cdata.set10('PREFIX', true)
|
||||
cdata_asm.set10('PREFIX', true)
|
||||
endif
|
||||
|
||||
if is_asm_enabled and host_machine.cpu_family().startswith('x86')
|
||||
|
||||
# NASM compiler support
|
||||
|
||||
nasm = find_program('nasm')
|
||||
|
||||
# check NASM version
|
||||
if nasm.found()
|
||||
nasm_r = run_command(nasm, '-v', check: true)
|
||||
|
||||
out = nasm_r.stdout().strip().split()
|
||||
if out[1].to_lower() == 'version'
|
||||
if out[2].version_compare('<2.14')
|
||||
error('nasm 2.14 or later is required, found nasm @0@'.format(out[2]))
|
||||
endif
|
||||
else
|
||||
error('unexpected nasm version string: @0@'.format(nasm_r.stdout()))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Generate config.asm
|
||||
config_asm_target = configure_file(output: 'config.asm', output_format: 'nasm', configuration: cdata_asm)
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
nasm_format = 'win'
|
||||
elif host_machine.system() in ['darwin', 'ios', 'tvos']
|
||||
nasm_format = 'macho'
|
||||
else
|
||||
nasm_format = 'elf'
|
||||
endif
|
||||
if host_machine.cpu_family() == 'x86_64'
|
||||
nasm_format += '64'
|
||||
else
|
||||
nasm_format += '32'
|
||||
endif
|
||||
|
||||
nasm_gen = generator(nasm,
|
||||
output: '@BASENAME@.obj',
|
||||
depfile: '@BASENAME@.obj.ndep',
|
||||
arguments: [
|
||||
'-f', nasm_format,
|
||||
'-I', '@0@/src/'.format(dav1d_src_root),
|
||||
'-I', '@0@/'.format(meson.current_build_dir()),
|
||||
'-MQ', '@OUTPUT@', '-MF', '@DEPFILE@',
|
||||
'@EXTRA_ARGS@',
|
||||
'@INPUT@',
|
||||
'-o', '@OUTPUT@'
|
||||
])
|
||||
endif
|
||||
|
||||
if is_asm_enabled and host_machine.cpu_family().startswith('riscv')
|
||||
as_option_code = '''__asm__ (
|
||||
".option arch, +v\n"
|
||||
"vsetivli zero, 0, e8, m1, ta, ma"
|
||||
);
|
||||
'''
|
||||
if not cc.compiles(as_option_code, name : 'RISC-V Vector')
|
||||
error('Compiler doesn\'t support \'.option arch\' asm directive. Update to binutils>=2.38 or clang>=17 or use \'-Denable_asm=false\'.')
|
||||
endif
|
||||
endif
|
||||
|
||||
# Generate config.h
|
||||
config_h_target = configure_file(output: 'config.h', configuration: cdata)
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Include subdir meson.build files
|
||||
# The order is important!
|
||||
|
||||
subdir('include')
|
||||
|
||||
subdir('doc')
|
||||
|
||||
subdir('src')
|
||||
|
||||
subdir('tools')
|
||||
|
||||
subdir('examples')
|
||||
|
||||
subdir('tests')
|
||||
75
media/libdav1d/src/meson_options.txt
Normal file
75
media/libdav1d/src/meson_options.txt
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# General options
|
||||
|
||||
option('bitdepths',
|
||||
type: 'array',
|
||||
choices: ['8', '16'],
|
||||
description: 'Enable only specified bitdepths')
|
||||
|
||||
option('enable_asm',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Build asm files, if available')
|
||||
|
||||
option('enable_tools',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Build dav1d cli tools')
|
||||
|
||||
option('enable_examples',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Build dav1d examples')
|
||||
|
||||
option('enable_tests',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Build dav1d tests')
|
||||
|
||||
option('enable_seek_stress',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Build seek_stress test tool')
|
||||
|
||||
option('enable_docs',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Build dav1d documentation')
|
||||
|
||||
option('logging',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Print error log messages using the provided callback function')
|
||||
|
||||
option('testdata_tests',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Run tests requiring the test data repository')
|
||||
|
||||
option('fuzzing_engine',
|
||||
type: 'combo',
|
||||
choices : ['none', 'libfuzzer', 'oss-fuzz'],
|
||||
value: 'none',
|
||||
description: 'Select the fuzzing engine')
|
||||
|
||||
option('fuzzer_ldflags',
|
||||
type: 'string',
|
||||
description: 'Extra LDFLAGS used during linking of fuzzing binaries')
|
||||
|
||||
option('stack_alignment',
|
||||
type: 'integer',
|
||||
value: 0)
|
||||
|
||||
option('xxhash_muxer',
|
||||
type : 'feature',
|
||||
value : 'auto')
|
||||
|
||||
option('trim_dsp',
|
||||
type: 'combo',
|
||||
choices: ['true', 'false', 'if-release'],
|
||||
value: 'if-release',
|
||||
description: 'Eliminate redundant DSP functions where possible')
|
||||
|
||||
option('macos_kperf',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Use the private macOS kperf API for benchmarking')
|
||||
15
media/libdav1d/src/package/crossfiles/aarch64-android.meson
Normal file
15
media/libdav1d/src/package/crossfiles/aarch64-android.meson
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[binaries]
|
||||
c = 'aarch64-linux-android21-clang'
|
||||
cpp = 'aarch64-linux-android21-clang++'
|
||||
ar = 'llvm-ar'
|
||||
strip = 'llvm-strip'
|
||||
pkgconfig = 'pkg-config'
|
||||
|
||||
[properties]
|
||||
needs_exe_wrapper = true
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[binaries]
|
||||
c = 'clang'
|
||||
cpp = 'clang++'
|
||||
ar = 'aarch64-linux-gnu-ar'
|
||||
strip = 'aarch64-linux-gnu-strip'
|
||||
exe_wrapper = 'qemu-aarch64'
|
||||
|
||||
[properties]
|
||||
c_args = '-target aarch64-linux-gnu'
|
||||
c_link_args = '-target aarch64-linux-gnu'
|
||||
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
12
media/libdav1d/src/package/crossfiles/aarch64-linux.meson
Normal file
12
media/libdav1d/src/package/crossfiles/aarch64-linux.meson
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[binaries]
|
||||
c = 'aarch64-linux-gnu-gcc'
|
||||
cpp = 'aarch64-linux-gnu-g++'
|
||||
ar = 'aarch64-linux-gnu-ar'
|
||||
strip = 'aarch64-linux-gnu-strip'
|
||||
exe_wrapper = 'qemu-aarch64'
|
||||
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[binaries]
|
||||
c = 'aarch64-w64-mingw32-clang'
|
||||
cpp = 'aarch64-w64-mingw32-clang++'
|
||||
ar = 'aarch64-w64-mingw32-ar'
|
||||
strip = 'aarch64-w64-mingw32-strip'
|
||||
pkgconfig = 'pkg-config'
|
||||
windres = 'aarch64-w64-mingw32-windres'
|
||||
|
||||
[properties]
|
||||
c_link_args = ['-static-libgcc']
|
||||
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
15
media/libdav1d/src/package/crossfiles/arm-android.meson
Normal file
15
media/libdav1d/src/package/crossfiles/arm-android.meson
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[binaries]
|
||||
c = 'armv7a-linux-androideabi21-clang'
|
||||
cpp = 'armv7a-linux-androideabi21-clang++'
|
||||
ar = 'llvm-ar'
|
||||
strip = 'llvm-strip'
|
||||
pkgconfig = 'pkg-config'
|
||||
|
||||
[properties]
|
||||
needs_exe_wrapper = true
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'arm'
|
||||
cpu = 'arm'
|
||||
endian = 'little'
|
||||
27
media/libdav1d/src/package/crossfiles/arm64-iPhoneOS.meson
Normal file
27
media/libdav1d/src/package/crossfiles/arm64-iPhoneOS.meson
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
[binaries]
|
||||
c = ['clang', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk']
|
||||
cpp = ['clang++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk']
|
||||
objc = ['clang', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk']
|
||||
objcpp = ['clang++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk']
|
||||
ar = 'ar'
|
||||
strip = 'strip'
|
||||
|
||||
[built-in options]
|
||||
c_args = ['-miphoneos-version-min=11.0']
|
||||
cpp_args = ['-miphoneos-version-min=11.0']
|
||||
c_link_args = ['-miphoneos-version-min=11.0']
|
||||
cpp_link_args = ['-miphoneos-version-min=11.0']
|
||||
objc_args = ['-miphoneos-version-min=11.0']
|
||||
objcpp_args = ['-miphoneos-version-min=11.0']
|
||||
|
||||
[properties]
|
||||
root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer'
|
||||
needs_exe_wrapper = true
|
||||
|
||||
[host_machine]
|
||||
system = 'darwin'
|
||||
subsystem = 'ios'
|
||||
kernel = 'xnu'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[binaries]
|
||||
c = 'armv7-w64-mingw32-clang'
|
||||
cpp = 'armv7-w64-mingw32-clang++'
|
||||
ar = 'armv7-w64-mingw32-ar'
|
||||
strip = 'armv7-w64-mingw32-strip'
|
||||
pkgconfig = 'pkg-config'
|
||||
windres = 'armv7-w64-mingw32-windres'
|
||||
|
||||
[properties]
|
||||
c_link_args = ['-static-libgcc']
|
||||
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'arm'
|
||||
cpu = 'armv7'
|
||||
endian = 'little'
|
||||
15
media/libdav1d/src/package/crossfiles/i686-linux32.meson
Normal file
15
media/libdav1d/src/package/crossfiles/i686-linux32.meson
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[binaries]
|
||||
c = 'gcc'
|
||||
cpp = 'g++'
|
||||
ar = 'ar'
|
||||
strip = 'strip'
|
||||
|
||||
[properties]
|
||||
c_link_args = ['-m32', '-Wl,-z,text']
|
||||
c_args = ['-m32']
|
||||
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = 'x86'
|
||||
cpu = 'i686'
|
||||
endian = 'little'
|
||||
16
media/libdav1d/src/package/crossfiles/i686-w64-mingw32.meson
Normal file
16
media/libdav1d/src/package/crossfiles/i686-w64-mingw32.meson
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
[binaries]
|
||||
c = 'i686-w64-mingw32-gcc'
|
||||
cpp = 'i686-w64-mingw32-g++'
|
||||
ar = 'i686-w64-mingw32-ar'
|
||||
strip = 'i686-w64-mingw32-strip'
|
||||
windres = 'i686-w64-mingw32-windres'
|
||||
exe_wrapper = 'wine'
|
||||
|
||||
[properties]
|
||||
c_link_args = ['-static-libgcc']
|
||||
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'x86'
|
||||
cpu = 'i686'
|
||||
endian = 'little'
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
[binaries]
|
||||
c = 'loongarch64-unknown-linux-gnu-gcc'
|
||||
cpp = 'loongarch64-unknown-linux-gnu-c++'
|
||||
ar = 'loongarch64-unknown-linux-gnu-ar'
|
||||
strip = 'loongarch64-unknown-linux-gnu-strip'
|
||||
pkgconfig = 'pkg-config'
|
||||
exe_wrapper = 'qemu-loongarch64'
|
||||
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = 'loongarch64'
|
||||
cpu = 'loongarch64'
|
||||
endian = 'little'
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[binaries]
|
||||
c = 'clang'
|
||||
cpp = 'clang++'
|
||||
ar = 'riscv64-linux-gnu-ar'
|
||||
strip = 'riscv64-linux-gnu-strip'
|
||||
exe_wrapper = 'qemu-riscv64'
|
||||
|
||||
[properties]
|
||||
c_args = '-target riscv64-linux-gnu'
|
||||
c_link_args = '-target riscv64-linux-gnu'
|
||||
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = 'riscv64'
|
||||
cpu = 'riscv64'
|
||||
endian = 'little'
|
||||
12
media/libdav1d/src/package/crossfiles/riscv64-linux.meson
Normal file
12
media/libdav1d/src/package/crossfiles/riscv64-linux.meson
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[binaries]
|
||||
c = 'riscv64-linux-gnu-gcc'
|
||||
cpp = 'riscv64-linux-gnu-g++'
|
||||
ar = 'riscv64-linux-gnu-ar'
|
||||
strip = 'riscv64-linux-gnu-strip'
|
||||
exe_wrapper = 'qemu-riscv64'
|
||||
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = 'riscv64'
|
||||
cpu = 'riscv64'
|
||||
endian = 'little'
|
||||
15
media/libdav1d/src/package/crossfiles/wasm32.meson
Normal file
15
media/libdav1d/src/package/crossfiles/wasm32.meson
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[binaries]
|
||||
c = 'emcc'
|
||||
cpp = 'em++'
|
||||
ar = 'emar'
|
||||
strip = 'emstrip'
|
||||
exe_wrapper = 'node'
|
||||
|
||||
[properties]
|
||||
c_link_args = ['-sEXPORT_ALL=1']
|
||||
|
||||
[host_machine]
|
||||
system = 'emscripten'
|
||||
cpu_family = 'wasm32'
|
||||
cpu = 'wasm32'
|
||||
endian = 'little'
|
||||
15
media/libdav1d/src/package/crossfiles/wasm64.meson
Normal file
15
media/libdav1d/src/package/crossfiles/wasm64.meson
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[binaries]
|
||||
c = 'emcc'
|
||||
cpp = 'em++'
|
||||
ar = 'emar'
|
||||
strip = 'emstrip'
|
||||
exe_wrapper = 'node'
|
||||
|
||||
[properties]
|
||||
c_link_args = ['-sEXPORT_ALL=1']
|
||||
|
||||
[host_machine]
|
||||
system = 'emscripten'
|
||||
cpu_family = 'wasm64'
|
||||
cpu = 'wasm64'
|
||||
endian = 'little'
|
||||
15
media/libdav1d/src/package/crossfiles/x86-android.meson
Normal file
15
media/libdav1d/src/package/crossfiles/x86-android.meson
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[binaries]
|
||||
c = 'i686-linux-android19-clang'
|
||||
cpp = 'i686-linux-android19-clang++'
|
||||
ar = 'llvm-ar'
|
||||
strip = 'llvm-strip'
|
||||
pkgconfig = 'pkg-config'
|
||||
|
||||
[properties]
|
||||
needs_exe_wrapper = true
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'x86'
|
||||
cpu = 'i686'
|
||||
endian = 'little'
|
||||
15
media/libdav1d/src/package/crossfiles/x86_64-android.meson
Normal file
15
media/libdav1d/src/package/crossfiles/x86_64-android.meson
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[binaries]
|
||||
c = 'x86_64-linux-android21-clang'
|
||||
cpp = 'x86_64-linux-android21-clang++'
|
||||
ar = 'llvm-ar'
|
||||
strip = 'llvm-strip'
|
||||
pkgconfig = 'pkg-config'
|
||||
|
||||
[properties]
|
||||
needs_exe_wrapper = true
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
[binaries]
|
||||
c = ['clang', '-arch', 'x86_64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk']
|
||||
cpp = ['clang++', '-arch', 'x86_64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk']
|
||||
objc = ['clang', '-arch', 'x86_64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk']
|
||||
objcpp = ['clang++', '-arch', 'x86_64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk']
|
||||
ar = 'ar'
|
||||
strip = 'strip'
|
||||
|
||||
[built-in options]
|
||||
c_args = ['-miphoneos-version-min=11.0']
|
||||
cpp_args = ['-miphoneos-version-min=11.0']
|
||||
c_link_args = ['-miphoneos-version-min=11.0']
|
||||
cpp_link_args = ['-miphoneos-version-min=11.0']
|
||||
objc_args = ['-miphoneos-version-min=11.0']
|
||||
objcpp_args = ['-miphoneos-version-min=11.0']
|
||||
|
||||
[properties]
|
||||
root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer'
|
||||
needs_exe_wrapper = true
|
||||
|
||||
[host_machine]
|
||||
system = 'darwin'
|
||||
subsystem = 'ios-simulator'
|
||||
kernel = 'xnu'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[binaries]
|
||||
c = 'x86_64-w64-mingw32-gcc'
|
||||
cpp = 'x86_64-w64-mingw32-g++'
|
||||
ar = 'x86_64-w64-mingw32-ar'
|
||||
strip = 'x86_64-w64-mingw32-strip'
|
||||
windres = 'x86_64-w64-mingw32-windres'
|
||||
exe_wrapper = 'wine'
|
||||
|
||||
[properties]
|
||||
c_link_args = ['-static-libgcc']
|
||||
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
24
media/libdav1d/src/package/snap/snapcraft.yaml
Normal file
24
media/libdav1d/src/package/snap/snapcraft.yaml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
name: dav1d
|
||||
base: core18
|
||||
version: git
|
||||
version-script: git describe HEAD --always
|
||||
summary: AV1 decoder from VideoLAN
|
||||
description: |
|
||||
A small and fast AV1 decoder from the people who brought you VLC.
|
||||
|
||||
grade: stable
|
||||
confinement: strict # use 'strict' once you have the right plugs and slots
|
||||
|
||||
apps:
|
||||
dav1d:
|
||||
command: usr/bin/dav1d
|
||||
plugs: [ 'home' ]
|
||||
|
||||
parts:
|
||||
dav1d:
|
||||
plugin: meson
|
||||
source: ../../
|
||||
build-packages: [ 'nasm' ]
|
||||
meson-parameters:
|
||||
- --prefix=/usr
|
||||
- --buildtype=release
|
||||
540
media/libdav1d/src/src/arm/32/cdef.S
Normal file
540
media/libdav1d/src/src/arm/32/cdef.S
Normal file
|
|
@ -0,0 +1,540 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2019, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
#include "cdef_tmpl.S"
|
||||
|
||||
// n1 = s0/d0
|
||||
// w1 = d0/q0
|
||||
// n2 = s4/d2
|
||||
// w2 = d2/q1
|
||||
.macro pad_top_bottom s1, s2, w, stride, n1, w1, n2, w2, align, ret
|
||||
tst r7, #1 // CDEF_HAVE_LEFT
|
||||
beq 2f
|
||||
// CDEF_HAVE_LEFT
|
||||
tst r7, #2 // CDEF_HAVE_RIGHT
|
||||
beq 1f
|
||||
// CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
ldrh r12, [\s1, #-2]
|
||||
vldr \n1, [\s1]
|
||||
vdup.16 d4, r12
|
||||
ldrh r12, [\s1, #\w]
|
||||
vmov.16 d4[1], r12
|
||||
ldrh r12, [\s2, #-2]
|
||||
vldr \n2, [\s2]
|
||||
vmov.16 d4[2], r12
|
||||
ldrh r12, [\s2, #\w]
|
||||
vmovl.u8 q0, d0
|
||||
vmov.16 d4[3], r12
|
||||
vmovl.u8 q1, d2
|
||||
vmovl.u8 q2, d4
|
||||
vstr s8, [r0, #-4]
|
||||
vst1.16 {\w1}, [r0, :\align]
|
||||
vstr s9, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
vstr s10, [r0, #-4]
|
||||
vst1.16 {\w2}, [r0, :\align]
|
||||
vstr s11, [r0, #2*\w]
|
||||
.if \ret
|
||||
pop {r4-r8,pc}
|
||||
.else
|
||||
add r0, r0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
1:
|
||||
// CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
ldrh r12, [\s1, #-2]
|
||||
vldr \n1, [\s1]
|
||||
vdup.16 d4, r12
|
||||
ldrh r12, [\s2, #-2]
|
||||
vldr \n2, [\s2]
|
||||
vmovl.u8 q0, d0
|
||||
vmov.16 d4[1], r12
|
||||
vmovl.u8 q1, d2
|
||||
vmovl.u8 q2, d4
|
||||
vstr s8, [r0, #-4]
|
||||
vst1.16 {\w1}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
vstr s9, [r0, #-4]
|
||||
vst1.16 {\w2}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
.if \ret
|
||||
pop {r4-r8,pc}
|
||||
.else
|
||||
add r0, r0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
2:
|
||||
// !CDEF_HAVE_LEFT
|
||||
tst r7, #2 // CDEF_HAVE_RIGHT
|
||||
beq 1f
|
||||
// !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
vldr \n1, [\s1]
|
||||
ldrh r12, [\s1, #\w]
|
||||
vldr \n2, [\s2]
|
||||
vdup.16 d4, r12
|
||||
ldrh r12, [\s2, #\w]
|
||||
vmovl.u8 q0, d0
|
||||
vmov.16 d4[1], r12
|
||||
vmovl.u8 q1, d2
|
||||
vmovl.u8 q2, d4
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\w1}, [r0, :\align]
|
||||
vstr s8, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\w2}, [r0, :\align]
|
||||
vstr s9, [r0, #2*\w]
|
||||
.if \ret
|
||||
pop {r4-r8,pc}
|
||||
.else
|
||||
add r0, r0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
1:
|
||||
// !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
vldr \n1, [\s1]
|
||||
vldr \n2, [\s2]
|
||||
vmovl.u8 q0, d0
|
||||
vmovl.u8 q1, d2
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\w1}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\w2}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
.if \ret
|
||||
pop {r4-r8,pc}
|
||||
.else
|
||||
add r0, r0, #2*\stride
|
||||
.endif
|
||||
3:
|
||||
.endm
|
||||
|
||||
.macro load_n_incr dst, src, incr, w
|
||||
.if \w == 4
|
||||
vld1.32 {\dst\()[0]}, [\src, :32], \incr
|
||||
.else
|
||||
vld1.8 {\dst\()}, [\src, :64], \incr
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// void dav1d_cdef_paddingX_8bpc_neon(uint16_t *tmp, const pixel *src,
|
||||
// ptrdiff_t src_stride, const pixel (*left)[2],
|
||||
// const pixel *const top,
|
||||
// const pixel *const bottom, int h,
|
||||
// enum CdefEdgeFlags edges);
|
||||
|
||||
// n1 = s0/d0
|
||||
// w1 = d0/q0
|
||||
// n2 = s4/d2
|
||||
// w2 = d2/q1
|
||||
.macro padding_func w, stride, n1, w1, n2, w2, align
|
||||
function cdef_padding\w\()_8bpc_neon, export=1
|
||||
push {r4-r8,lr}
|
||||
ldrd r4, r5, [sp, #24]
|
||||
ldrd r6, r7, [sp, #32]
|
||||
cmp r7, #0xf // fully edged
|
||||
beq cdef_padding\w\()_edged_8bpc_neon
|
||||
vmov.i16 q3, #0x8000
|
||||
tst r7, #4 // CDEF_HAVE_TOP
|
||||
bne 1f
|
||||
// !CDEF_HAVE_TOP
|
||||
sub r12, r0, #2*(2*\stride+2)
|
||||
vmov.i16 q2, #0x8000
|
||||
vst1.16 {q2,q3}, [r12]!
|
||||
.if \w == 8
|
||||
vst1.16 {q2,q3}, [r12]!
|
||||
.endif
|
||||
b 3f
|
||||
1:
|
||||
// CDEF_HAVE_TOP
|
||||
add r8, r4, r2
|
||||
sub r0, r0, #2*(2*\stride)
|
||||
pad_top_bottom r4, r8, \w, \stride, \n1, \w1, \n2, \w2, \align, 0
|
||||
|
||||
// Middle section
|
||||
3:
|
||||
tst r7, #1 // CDEF_HAVE_LEFT
|
||||
beq 2f
|
||||
// CDEF_HAVE_LEFT
|
||||
tst r7, #2 // CDEF_HAVE_RIGHT
|
||||
beq 1f
|
||||
// CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
0:
|
||||
vld1.16 {d2[]}, [r3, :16]!
|
||||
ldrh r12, [r1, #\w]
|
||||
load_n_incr d0, r1, r2, \w
|
||||
subs r6, r6, #1
|
||||
vmov.16 d2[1], r12
|
||||
vmovl.u8 q0, d0
|
||||
vmovl.u8 q1, d2
|
||||
vstr s4, [r0, #-4]
|
||||
vst1.16 {\w1}, [r0, :\align]
|
||||
vstr s5, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
bgt 0b
|
||||
b 3f
|
||||
1:
|
||||
// CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
vld1.16 {d2[]}, [r3, :16]!
|
||||
load_n_incr d0, r1, r2, \w
|
||||
subs r6, r6, #1
|
||||
vmovl.u8 q0, d0
|
||||
vmovl.u8 q1, d2
|
||||
vstr s4, [r0, #-4]
|
||||
vst1.16 {\w1}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
bgt 1b
|
||||
b 3f
|
||||
2:
|
||||
tst r7, #2 // CDEF_HAVE_RIGHT
|
||||
beq 1f
|
||||
// !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
0:
|
||||
ldrh r12, [r1, #\w]
|
||||
load_n_incr d0, r1, r2, \w
|
||||
vdup.16 d2, r12
|
||||
subs r6, r6, #1
|
||||
vmovl.u8 q0, d0
|
||||
vmovl.u8 q1, d2
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\w1}, [r0, :\align]
|
||||
vstr s4, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
bgt 0b
|
||||
b 3f
|
||||
1:
|
||||
// !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
load_n_incr d0, r1, r2, \w
|
||||
subs r6, r6, #1
|
||||
vmovl.u8 q0, d0
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\w1}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
bgt 1b
|
||||
|
||||
3:
|
||||
tst r7, #8 // CDEF_HAVE_BOTTOM
|
||||
bne 1f
|
||||
// !CDEF_HAVE_BOTTOM
|
||||
sub r12, r0, #4
|
||||
vmov.i16 q2, #0x8000
|
||||
vst1.16 {q2,q3}, [r12]!
|
||||
.if \w == 8
|
||||
vst1.16 {q2,q3}, [r12]!
|
||||
.endif
|
||||
pop {r4-r8,pc}
|
||||
1:
|
||||
// CDEF_HAVE_BOTTOM
|
||||
add r8, r5, r2
|
||||
pad_top_bottom r5, r8, \w, \stride, \n1, \w1, \n2, \w2, \align, 1
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
padding_func 8, 16, d0, q0, d2, q1, 128
|
||||
padding_func 4, 8, s0, d0, s4, d2, 64
|
||||
|
||||
// void cdef_paddingX_edged_8bpc_neon(uint16_t *tmp, const pixel *src,
|
||||
// ptrdiff_t src_stride, const pixel (*left)[2],
|
||||
// const pixel *const top,
|
||||
// const pixel *const bottom, int h,
|
||||
// enum CdefEdgeFlags edges);
|
||||
|
||||
.macro padding_func_edged w, stride, reg, align
|
||||
function cdef_padding\w\()_edged_8bpc_neon
|
||||
sub r0, r0, #(2*\stride)
|
||||
|
||||
ldrh r12, [r4, #-2]
|
||||
vldr \reg, [r4]
|
||||
add r8, r4, r2
|
||||
strh r12, [r0, #-2]
|
||||
ldrh r12, [r4, #\w]
|
||||
vstr \reg, [r0]
|
||||
strh r12, [r0, #\w]
|
||||
|
||||
ldrh r12, [r8, #-2]
|
||||
vldr \reg, [r8]
|
||||
strh r12, [r0, #\stride-2]
|
||||
ldrh r12, [r8, #\w]
|
||||
vstr \reg, [r0, #\stride]
|
||||
strh r12, [r0, #\stride+\w]
|
||||
add r0, r0, #2*\stride
|
||||
|
||||
0:
|
||||
ldrh r12, [r3], #2
|
||||
vldr \reg, [r1]
|
||||
str r12, [r0, #-2]
|
||||
ldrh r12, [r1, #\w]
|
||||
add r1, r1, r2
|
||||
subs r6, r6, #1
|
||||
vstr \reg, [r0]
|
||||
str r12, [r0, #\w]
|
||||
add r0, r0, #\stride
|
||||
bgt 0b
|
||||
|
||||
ldrh r12, [r5, #-2]
|
||||
vldr \reg, [r5]
|
||||
add r8, r5, r2
|
||||
strh r12, [r0, #-2]
|
||||
ldrh r12, [r5, #\w]
|
||||
vstr \reg, [r0]
|
||||
strh r12, [r0, #\w]
|
||||
|
||||
ldrh r12, [r8, #-2]
|
||||
vldr \reg, [r8]
|
||||
strh r12, [r0, #\stride-2]
|
||||
ldrh r12, [r8, #\w]
|
||||
vstr \reg, [r0, #\stride]
|
||||
strh r12, [r0, #\stride+\w]
|
||||
|
||||
pop {r4-r8,pc}
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
padding_func_edged 8, 16, d0, 64
|
||||
padding_func_edged 4, 8, s0, 32
|
||||
|
||||
tables
|
||||
|
||||
filter 8, 8
|
||||
filter 4, 8
|
||||
|
||||
find_dir 8
|
||||
|
||||
.macro load_px_8 d11, d12, d21, d22, w
|
||||
.if \w == 8
|
||||
add r6, r2, r9 // x + off
|
||||
sub r9, r2, r9 // x - off
|
||||
vld1.8 {\d11}, [r6] // p0
|
||||
add r6, r6, #16 // += stride
|
||||
vld1.8 {\d21}, [r9] // p1
|
||||
add r9, r9, #16 // += stride
|
||||
vld1.8 {\d12}, [r6] // p0
|
||||
vld1.8 {\d22}, [r9] // p1
|
||||
.else
|
||||
add r6, r2, r9 // x + off
|
||||
sub r9, r2, r9 // x - off
|
||||
vld1.32 {\d11[0]}, [r6] // p0
|
||||
add r6, r6, #8 // += stride
|
||||
vld1.32 {\d21[0]}, [r9] // p1
|
||||
add r9, r9, #8 // += stride
|
||||
vld1.32 {\d11[1]}, [r6] // p0
|
||||
add r6, r6, #8 // += stride
|
||||
vld1.32 {\d21[1]}, [r9] // p1
|
||||
add r9, r9, #8 // += stride
|
||||
vld1.32 {\d12[0]}, [r6] // p0
|
||||
add r6, r6, #8 // += stride
|
||||
vld1.32 {\d22[0]}, [r9] // p1
|
||||
add r9, r9, #8 // += stride
|
||||
vld1.32 {\d12[1]}, [r6] // p0
|
||||
vld1.32 {\d22[1]}, [r9] // p1
|
||||
.endif
|
||||
.endm
|
||||
.macro handle_pixel_8 s1, s2, thresh_vec, shift, tap, min
|
||||
.if \min
|
||||
vmin.u8 q3, q3, \s1
|
||||
vmax.u8 q4, q4, \s1
|
||||
vmin.u8 q3, q3, \s2
|
||||
vmax.u8 q4, q4, \s2
|
||||
.endif
|
||||
vabd.u8 q8, q0, \s1 // abs(diff)
|
||||
vabd.u8 q11, q0, \s2 // abs(diff)
|
||||
vshl.u8 q9, q8, \shift // abs(diff) >> shift
|
||||
vshl.u8 q12, q11, \shift // abs(diff) >> shift
|
||||
vqsub.u8 q9, \thresh_vec, q9 // clip = imax(0, threshold - (abs(diff) >> shift))
|
||||
vqsub.u8 q12, \thresh_vec, q12// clip = imax(0, threshold - (abs(diff) >> shift))
|
||||
vcgt.u8 q10, q0, \s1 // px > p0
|
||||
vcgt.u8 q13, q0, \s2 // px > p1
|
||||
vmin.u8 q9, q9, q8 // imin(abs(diff), clip)
|
||||
vmin.u8 q12, q12, q11 // imin(abs(diff), clip)
|
||||
vneg.s8 q8, q9 // -imin()
|
||||
vneg.s8 q11, q12 // -imin()
|
||||
vbsl q10, q8, q9 // constrain() = imax(imin(diff, clip), -clip)
|
||||
vdup.8 d18, \tap // taps[k]
|
||||
vbsl q13, q11, q12 // constrain() = imax(imin(diff, clip), -clip)
|
||||
vmlal.s8 q1, d20, d18 // sum += taps[k] * constrain()
|
||||
vmlal.s8 q1, d26, d18 // sum += taps[k] * constrain()
|
||||
vmlal.s8 q2, d21, d18 // sum += taps[k] * constrain()
|
||||
vmlal.s8 q2, d27, d18 // sum += taps[k] * constrain()
|
||||
.endm
|
||||
|
||||
// void cdef_filterX_edged_neon(pixel *dst, ptrdiff_t dst_stride,
|
||||
// const uint16_t *tmp, int pri_strength,
|
||||
// int sec_strength, int dir, int damping,
|
||||
// int h, size_t edges);
|
||||
.macro filter_func_8 w, pri, sec, min, suffix
|
||||
function cdef_filter\w\suffix\()_edged_neon
|
||||
.if \pri
|
||||
movrel_local r8, pri_taps
|
||||
and r9, r3, #1
|
||||
add r8, r8, r9, lsl #1
|
||||
.endif
|
||||
movrel_local r9, directions\w
|
||||
add r5, r9, r5, lsl #1
|
||||
vmov.u8 d17, #7
|
||||
vdup.8 d16, r6 // damping
|
||||
|
||||
vmov.8 d8[0], r3
|
||||
vmov.8 d8[1], r4
|
||||
vclz.i8 d8, d8 // clz(threshold)
|
||||
vsub.i8 d8, d17, d8 // ulog2(threshold)
|
||||
vqsub.u8 d8, d16, d8 // shift = imax(0, damping - ulog2(threshold))
|
||||
vneg.s8 d8, d8 // -shift
|
||||
.if \sec
|
||||
vdup.8 q6, d8[1]
|
||||
.endif
|
||||
.if \pri
|
||||
vdup.8 q5, d8[0]
|
||||
.endif
|
||||
|
||||
1:
|
||||
.if \w == 8
|
||||
add r12, r2, #16
|
||||
vld1.8 {d0}, [r2, :64] // px
|
||||
vld1.8 {d1}, [r12, :64] // px
|
||||
.else
|
||||
add r12, r2, #8
|
||||
vld1.32 {d0[0]}, [r2, :32] // px
|
||||
add r9, r2, #2*8
|
||||
vld1.32 {d0[1]}, [r12, :32] // px
|
||||
add r12, r12, #2*8
|
||||
vld1.32 {d1[0]}, [r9, :32] // px
|
||||
vld1.32 {d1[1]}, [r12, :32] // px
|
||||
.endif
|
||||
|
||||
vmov.u8 q1, #0 // sum
|
||||
vmov.u8 q2, #0 // sum
|
||||
.if \min
|
||||
vmov.u16 q3, q0 // min
|
||||
vmov.u16 q4, q0 // max
|
||||
.endif
|
||||
|
||||
// Instead of loading sec_taps 2, 1 from memory, just set it
|
||||
// to 2 initially and decrease for the second round.
|
||||
// This is also used as loop counter.
|
||||
mov lr, #2 // sec_taps[0]
|
||||
|
||||
2:
|
||||
.if \pri
|
||||
ldrsb r9, [r5] // off1
|
||||
|
||||
load_px_8 d28, d29, d30, d31, \w
|
||||
.endif
|
||||
|
||||
.if \sec
|
||||
add r5, r5, #4 // +2*2
|
||||
ldrsb r9, [r5] // off2
|
||||
.endif
|
||||
|
||||
.if \pri
|
||||
ldrb r12, [r8] // *pri_taps
|
||||
vdup.8 q7, r3 // threshold
|
||||
|
||||
handle_pixel_8 q14, q15, q7, q5, r12, \min
|
||||
.endif
|
||||
|
||||
.if \sec
|
||||
load_px_8 d28, d29, d30, d31, \w
|
||||
|
||||
add r5, r5, #8 // +2*4
|
||||
ldrsb r9, [r5] // off3
|
||||
|
||||
vdup.8 q7, r4 // threshold
|
||||
|
||||
handle_pixel_8 q14, q15, q7, q6, lr, \min
|
||||
|
||||
load_px_8 d28, d29, d30, d31, \w
|
||||
|
||||
handle_pixel_8 q14, q15, q7, q6, lr, \min
|
||||
|
||||
sub r5, r5, #11 // r5 -= 2*(2+4); r5 += 1;
|
||||
.else
|
||||
add r5, r5, #1 // r5 += 1
|
||||
.endif
|
||||
subs lr, lr, #1 // sec_tap-- (value)
|
||||
.if \pri
|
||||
add r8, r8, #1 // pri_taps++ (pointer)
|
||||
.endif
|
||||
bne 2b
|
||||
|
||||
vshr.s16 q14, q1, #15 // -(sum < 0)
|
||||
vshr.s16 q15, q2, #15 // -(sum < 0)
|
||||
vadd.i16 q1, q1, q14 // sum - (sum < 0)
|
||||
vadd.i16 q2, q2, q15 // sum - (sum < 0)
|
||||
vrshr.s16 q1, q1, #4 // (8 + sum - (sum < 0)) >> 4
|
||||
vrshr.s16 q2, q2, #4 // (8 + sum - (sum < 0)) >> 4
|
||||
vaddw.u8 q1, q1, d0 // px + (8 + sum ...) >> 4
|
||||
vaddw.u8 q2, q2, d1 // px + (8 + sum ...) >> 4
|
||||
vqmovun.s16 d0, q1
|
||||
vqmovun.s16 d1, q2
|
||||
.if \min
|
||||
vmin.u8 q0, q0, q4
|
||||
vmax.u8 q0, q0, q3 // iclip(px + .., min, max)
|
||||
.endif
|
||||
.if \w == 8
|
||||
vst1.8 {d0}, [r0, :64], r1
|
||||
add r2, r2, #2*16 // tmp += 2*tmp_stride
|
||||
subs r7, r7, #2 // h -= 2
|
||||
vst1.8 {d1}, [r0, :64], r1
|
||||
.else
|
||||
vst1.32 {d0[0]}, [r0, :32], r1
|
||||
add r2, r2, #4*8 // tmp += 4*tmp_stride
|
||||
vst1.32 {d0[1]}, [r0, :32], r1
|
||||
subs r7, r7, #4 // h -= 4
|
||||
vst1.32 {d1[0]}, [r0, :32], r1
|
||||
vst1.32 {d1[1]}, [r0, :32], r1
|
||||
.endif
|
||||
|
||||
// Reset pri_taps and directions back to the original point
|
||||
sub r5, r5, #2
|
||||
.if \pri
|
||||
sub r8, r8, #2
|
||||
.endif
|
||||
|
||||
bgt 1b
|
||||
vpop {q4-q7}
|
||||
pop {r4-r9,pc}
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
.macro filter_8 w
|
||||
filter_func_8 \w, pri=1, sec=0, min=0, suffix=_pri
|
||||
filter_func_8 \w, pri=0, sec=1, min=0, suffix=_sec
|
||||
filter_func_8 \w, pri=1, sec=1, min=1, suffix=_pri_sec
|
||||
.endm
|
||||
|
||||
filter_8 8
|
||||
filter_8 4
|
||||
233
media/libdav1d/src/src/arm/32/cdef16.S
Normal file
233
media/libdav1d/src/src/arm/32/cdef16.S
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2020, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
#include "cdef_tmpl.S"
|
||||
|
||||
// r1 = d0/q0
|
||||
// r2 = d2/q1
|
||||
.macro pad_top_bot_16 s1, s2, w, stride, r1, r2, align, ret
|
||||
tst r7, #1 // CDEF_HAVE_LEFT
|
||||
beq 2f
|
||||
// CDEF_HAVE_LEFT
|
||||
tst r7, #2 // CDEF_HAVE_RIGHT
|
||||
beq 1f
|
||||
// CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
vldr s8, [\s1, #-4]
|
||||
vld1.16 {\r1}, [\s1, :\align]
|
||||
vldr s9, [\s1, #2*\w]
|
||||
vldr s10, [\s2, #-4]
|
||||
vld1.16 {\r2}, [\s2, :\align]
|
||||
vldr s11, [\s2, #2*\w]
|
||||
vstr s8, [r0, #-4]
|
||||
vst1.16 {\r1}, [r0, :\align]
|
||||
vstr s9, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
vstr s10, [r0, #-4]
|
||||
vst1.16 {\r2}, [r0, :\align]
|
||||
vstr s11, [r0, #2*\w]
|
||||
.if \ret
|
||||
pop {r4-r8,pc}
|
||||
.else
|
||||
add r0, r0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
1:
|
||||
// CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
vldr s8, [\s1, #-4]
|
||||
vld1.16 {\r1}, [\s1, :\align]
|
||||
vldr s9, [\s2, #-4]
|
||||
vld1.16 {\r2}, [\s2, :\align]
|
||||
vstr s8, [r0, #-4]
|
||||
vst1.16 {\r1}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
vstr s9, [r0, #-4]
|
||||
vst1.16 {\r2}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
.if \ret
|
||||
pop {r4-r8,pc}
|
||||
.else
|
||||
add r0, r0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
2:
|
||||
// !CDEF_HAVE_LEFT
|
||||
tst r7, #2 // CDEF_HAVE_RIGHT
|
||||
beq 1f
|
||||
// !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
vld1.16 {\r1}, [\s1, :\align]
|
||||
vldr s8, [\s1, #2*\w]
|
||||
vld1.16 {\r2}, [\s2, :\align]
|
||||
vldr s9, [\s2, #2*\w]
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\r1}, [r0, :\align]
|
||||
vstr s8, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\r2}, [r0, :\align]
|
||||
vstr s9, [r0, #2*\w]
|
||||
.if \ret
|
||||
pop {r4-r8,pc}
|
||||
.else
|
||||
add r0, r0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
1:
|
||||
// !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
vld1.16 {\r1}, [\s1, :\align]
|
||||
vld1.16 {\r2}, [\s2, :\align]
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\r1}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\r2}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
.if \ret
|
||||
pop {r4-r8,pc}
|
||||
.else
|
||||
add r0, r0, #2*\stride
|
||||
.endif
|
||||
3:
|
||||
.endm
|
||||
|
||||
// void dav1d_cdef_paddingX_16bpc_neon(uint16_t *tmp, const pixel *src,
|
||||
// ptrdiff_t src_stride, const pixel (*left)[2],
|
||||
// const pixel *const top,
|
||||
// const pixel *const bottom, int h,
|
||||
// enum CdefEdgeFlags edges);
|
||||
|
||||
// r1 = d0/q0
|
||||
// r2 = d2/q1
|
||||
.macro padding_func_16 w, stride, r1, r2, align
|
||||
function cdef_padding\w\()_16bpc_neon, export=1
|
||||
push {r4-r8,lr}
|
||||
ldrd r4, r5, [sp, #24]
|
||||
ldrd r6, r7, [sp, #32]
|
||||
vmov.i16 q3, #0x8000
|
||||
tst r7, #4 // CDEF_HAVE_TOP
|
||||
bne 1f
|
||||
// !CDEF_HAVE_TOP
|
||||
sub r12, r0, #2*(2*\stride+2)
|
||||
vmov.i16 q2, #0x8000
|
||||
vst1.16 {q2,q3}, [r12]!
|
||||
.if \w == 8
|
||||
vst1.16 {q2,q3}, [r12]!
|
||||
.endif
|
||||
b 3f
|
||||
1:
|
||||
// CDEF_HAVE_TOP
|
||||
add r8, r4, r2
|
||||
sub r0, r0, #2*(2*\stride)
|
||||
pad_top_bot_16 r4, r8, \w, \stride, \r1, \r2, \align, 0
|
||||
|
||||
// Middle section
|
||||
3:
|
||||
tst r7, #1 // CDEF_HAVE_LEFT
|
||||
beq 2f
|
||||
// CDEF_HAVE_LEFT
|
||||
tst r7, #2 // CDEF_HAVE_RIGHT
|
||||
beq 1f
|
||||
// CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
0:
|
||||
vld1.32 {d2[]}, [r3, :32]!
|
||||
vldr s5, [r1, #2*\w]
|
||||
vld1.16 {\r1}, [r1, :\align], r2
|
||||
subs r6, r6, #1
|
||||
vstr s4, [r0, #-4]
|
||||
vst1.16 {\r1}, [r0, :\align]
|
||||
vstr s5, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
bgt 0b
|
||||
b 3f
|
||||
1:
|
||||
// CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
vld1.32 {d2[]}, [r3, :32]!
|
||||
vld1.16 {\r1}, [r1, :\align], r2
|
||||
subs r6, r6, #1
|
||||
vstr s4, [r0, #-4]
|
||||
vst1.16 {\r1}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
bgt 1b
|
||||
b 3f
|
||||
2:
|
||||
tst r7, #2 // CDEF_HAVE_RIGHT
|
||||
beq 1f
|
||||
// !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
0:
|
||||
vldr s4, [r1, #2*\w]
|
||||
vld1.16 {\r1}, [r1, :\align], r2
|
||||
subs r6, r6, #1
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\r1}, [r0, :\align]
|
||||
vstr s4, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
bgt 0b
|
||||
b 3f
|
||||
1:
|
||||
// !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
vld1.16 {\r1}, [r1, :\align], r2
|
||||
subs r6, r6, #1
|
||||
vstr s12, [r0, #-4]
|
||||
vst1.16 {\r1}, [r0, :\align]
|
||||
vstr s12, [r0, #2*\w]
|
||||
add r0, r0, #2*\stride
|
||||
bgt 1b
|
||||
|
||||
3:
|
||||
tst r7, #8 // CDEF_HAVE_BOTTOM
|
||||
bne 1f
|
||||
// !CDEF_HAVE_BOTTOM
|
||||
sub r12, r0, #4
|
||||
vmov.i16 q2, #0x8000
|
||||
vst1.16 {q2,q3}, [r12]!
|
||||
.if \w == 8
|
||||
vst1.16 {q2,q3}, [r12]!
|
||||
.endif
|
||||
pop {r4-r8,pc}
|
||||
1:
|
||||
// CDEF_HAVE_BOTTOM
|
||||
add r8, r5, r2
|
||||
pad_top_bot_16 r5, r8, \w, \stride, \r1, \r2, \align, 1
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
padding_func_16 8, 16, q0, q1, 128
|
||||
padding_func_16 4, 8, d0, d2, 64
|
||||
|
||||
tables
|
||||
|
||||
filter 8, 16
|
||||
filter 4, 16
|
||||
|
||||
find_dir 16
|
||||
515
media/libdav1d/src/src/arm/32/cdef_tmpl.S
Normal file
515
media/libdav1d/src/src/arm/32/cdef_tmpl.S
Normal file
|
|
@ -0,0 +1,515 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2020, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
.macro dir_table w, stride
|
||||
const directions\w
|
||||
.byte -1 * \stride + 1, -2 * \stride + 2
|
||||
.byte 0 * \stride + 1, -1 * \stride + 2
|
||||
.byte 0 * \stride + 1, 0 * \stride + 2
|
||||
.byte 0 * \stride + 1, 1 * \stride + 2
|
||||
.byte 1 * \stride + 1, 2 * \stride + 2
|
||||
.byte 1 * \stride + 0, 2 * \stride + 1
|
||||
.byte 1 * \stride + 0, 2 * \stride + 0
|
||||
.byte 1 * \stride + 0, 2 * \stride - 1
|
||||
// Repeated, to avoid & 7
|
||||
.byte -1 * \stride + 1, -2 * \stride + 2
|
||||
.byte 0 * \stride + 1, -1 * \stride + 2
|
||||
.byte 0 * \stride + 1, 0 * \stride + 2
|
||||
.byte 0 * \stride + 1, 1 * \stride + 2
|
||||
.byte 1 * \stride + 1, 2 * \stride + 2
|
||||
.byte 1 * \stride + 0, 2 * \stride + 1
|
||||
endconst
|
||||
.endm
|
||||
|
||||
.macro tables
|
||||
dir_table 8, 16
|
||||
dir_table 4, 8
|
||||
|
||||
const pri_taps
|
||||
.byte 4, 2, 3, 3
|
||||
endconst
|
||||
.endm
|
||||
|
||||
.macro load_px d11, d12, d21, d22, w
|
||||
.if \w == 8
|
||||
add r6, r2, r9, lsl #1 // x + off
|
||||
sub r9, r2, r9, lsl #1 // x - off
|
||||
vld1.16 {\d11,\d12}, [r6] // p0
|
||||
vld1.16 {\d21,\d22}, [r9] // p1
|
||||
.else
|
||||
add r6, r2, r9, lsl #1 // x + off
|
||||
sub r9, r2, r9, lsl #1 // x - off
|
||||
vld1.16 {\d11}, [r6] // p0
|
||||
add r6, r6, #2*8 // += stride
|
||||
vld1.16 {\d21}, [r9] // p1
|
||||
add r9, r9, #2*8 // += stride
|
||||
vld1.16 {\d12}, [r6] // p0
|
||||
vld1.16 {\d22}, [r9] // p1
|
||||
.endif
|
||||
.endm
|
||||
.macro handle_pixel s1, s2, thresh_vec, shift, tap, min
|
||||
.if \min
|
||||
vmin.u16 q2, q2, \s1
|
||||
vmax.s16 q3, q3, \s1
|
||||
vmin.u16 q2, q2, \s2
|
||||
vmax.s16 q3, q3, \s2
|
||||
.endif
|
||||
vabd.u16 q8, q0, \s1 // abs(diff)
|
||||
vabd.u16 q11, q0, \s2 // abs(diff)
|
||||
vshl.u16 q9, q8, \shift // abs(diff) >> shift
|
||||
vshl.u16 q12, q11, \shift // abs(diff) >> shift
|
||||
vqsub.u16 q9, \thresh_vec, q9 // clip = imax(0, threshold - (abs(diff) >> shift))
|
||||
vqsub.u16 q12, \thresh_vec, q12// clip = imax(0, threshold - (abs(diff) >> shift))
|
||||
vsub.i16 q10, \s1, q0 // diff = p0 - px
|
||||
vsub.i16 q13, \s2, q0 // diff = p1 - px
|
||||
vneg.s16 q8, q9 // -clip
|
||||
vneg.s16 q11, q12 // -clip
|
||||
vmin.s16 q10, q10, q9 // imin(diff, clip)
|
||||
vmin.s16 q13, q13, q12 // imin(diff, clip)
|
||||
vdup.16 q9, \tap // taps[k]
|
||||
vmax.s16 q10, q10, q8 // constrain() = imax(imin(diff, clip), -clip)
|
||||
vmax.s16 q13, q13, q11 // constrain() = imax(imin(diff, clip), -clip)
|
||||
vmla.i16 q1, q10, q9 // sum += taps[k] * constrain()
|
||||
vmla.i16 q1, q13, q9 // sum += taps[k] * constrain()
|
||||
.endm
|
||||
|
||||
// void dav1d_cdef_filterX_Ybpc_neon(pixel *dst, ptrdiff_t dst_stride,
|
||||
// const uint16_t *tmp, int pri_strength,
|
||||
// int sec_strength, int dir, int damping,
|
||||
// int h, size_t edges);
|
||||
.macro filter_func w, bpc, pri, sec, min, suffix
|
||||
function cdef_filter\w\suffix\()_\bpc\()bpc_neon
|
||||
.if \bpc == 8
|
||||
cmp r8, #0xf
|
||||
beq cdef_filter\w\suffix\()_edged_neon
|
||||
.endif
|
||||
.if \pri
|
||||
.if \bpc == 16
|
||||
clz r9, r9
|
||||
sub r9, r9, #24 // -bitdepth_min_8
|
||||
neg r9, r9 // bitdepth_min_8
|
||||
.endif
|
||||
movrel_local r8, pri_taps
|
||||
.if \bpc == 16
|
||||
lsr r9, r3, r9 // pri_strength >> bitdepth_min_8
|
||||
and r9, r9, #1 // (pri_strength >> bitdepth_min_8) & 1
|
||||
.else
|
||||
and r9, r3, #1
|
||||
.endif
|
||||
add r8, r8, r9, lsl #1
|
||||
.endif
|
||||
movrel_local r9, directions\w
|
||||
add r5, r9, r5, lsl #1
|
||||
vmov.u16 d17, #15
|
||||
vdup.16 d16, r6 // damping
|
||||
|
||||
.if \pri
|
||||
vdup.16 q5, r3 // threshold
|
||||
.endif
|
||||
.if \sec
|
||||
vdup.16 q7, r4 // threshold
|
||||
.endif
|
||||
vmov.16 d8[0], r3
|
||||
vmov.16 d8[1], r4
|
||||
vclz.i16 d8, d8 // clz(threshold)
|
||||
vsub.i16 d8, d17, d8 // ulog2(threshold)
|
||||
vqsub.u16 d8, d16, d8 // shift = imax(0, damping - ulog2(threshold))
|
||||
vneg.s16 d8, d8 // -shift
|
||||
.if \sec
|
||||
vdup.16 q6, d8[1]
|
||||
.endif
|
||||
.if \pri
|
||||
vdup.16 q4, d8[0]
|
||||
.endif
|
||||
|
||||
1:
|
||||
.if \w == 8
|
||||
vld1.16 {q0}, [r2, :128] // px
|
||||
.else
|
||||
add r12, r2, #2*8
|
||||
vld1.16 {d0}, [r2, :64] // px
|
||||
vld1.16 {d1}, [r12, :64] // px
|
||||
.endif
|
||||
|
||||
vmov.u16 q1, #0 // sum
|
||||
.if \min
|
||||
vmov.u16 q2, q0 // min
|
||||
vmov.u16 q3, q0 // max
|
||||
.endif
|
||||
|
||||
// Instead of loading sec_taps 2, 1 from memory, just set it
|
||||
// to 2 initially and decrease for the second round.
|
||||
// This is also used as loop counter.
|
||||
mov lr, #2 // sec_taps[0]
|
||||
|
||||
2:
|
||||
.if \pri
|
||||
ldrsb r9, [r5] // off1
|
||||
|
||||
load_px d28, d29, d30, d31, \w
|
||||
.endif
|
||||
|
||||
.if \sec
|
||||
add r5, r5, #4 // +2*2
|
||||
ldrsb r9, [r5] // off2
|
||||
.endif
|
||||
|
||||
.if \pri
|
||||
ldrb r12, [r8] // *pri_taps
|
||||
|
||||
handle_pixel q14, q15, q5, q4, r12, \min
|
||||
.endif
|
||||
|
||||
.if \sec
|
||||
load_px d28, d29, d30, d31, \w
|
||||
|
||||
add r5, r5, #8 // +2*4
|
||||
ldrsb r9, [r5] // off3
|
||||
|
||||
handle_pixel q14, q15, q7, q6, lr, \min
|
||||
|
||||
load_px d28, d29, d30, d31, \w
|
||||
|
||||
handle_pixel q14, q15, q7, q6, lr, \min
|
||||
|
||||
sub r5, r5, #11 // r5 -= 2*(2+4); r5 += 1;
|
||||
.else
|
||||
add r5, r5, #1 // r5 += 1
|
||||
.endif
|
||||
subs lr, lr, #1 // sec_tap-- (value)
|
||||
.if \pri
|
||||
add r8, r8, #1 // pri_taps++ (pointer)
|
||||
.endif
|
||||
bne 2b
|
||||
|
||||
vshr.s16 q14, q1, #15 // -(sum < 0)
|
||||
vadd.i16 q1, q1, q14 // sum - (sum < 0)
|
||||
vrshr.s16 q1, q1, #4 // (8 + sum - (sum < 0)) >> 4
|
||||
vadd.i16 q0, q0, q1 // px + (8 + sum ...) >> 4
|
||||
.if \min
|
||||
vmin.s16 q0, q0, q3
|
||||
vmax.s16 q0, q0, q2 // iclip(px + .., min, max)
|
||||
.endif
|
||||
.if \bpc == 8
|
||||
vmovn.u16 d0, q0
|
||||
.endif
|
||||
.if \w == 8
|
||||
add r2, r2, #2*16 // tmp += tmp_stride
|
||||
subs r7, r7, #1 // h--
|
||||
.if \bpc == 8
|
||||
vst1.8 {d0}, [r0, :64], r1
|
||||
.else
|
||||
vst1.16 {q0}, [r0, :128], r1
|
||||
.endif
|
||||
.else
|
||||
.if \bpc == 8
|
||||
vst1.32 {d0[0]}, [r0, :32], r1
|
||||
.else
|
||||
vst1.16 {d0}, [r0, :64], r1
|
||||
.endif
|
||||
add r2, r2, #2*16 // tmp += 2*tmp_stride
|
||||
subs r7, r7, #2 // h -= 2
|
||||
.if \bpc == 8
|
||||
vst1.32 {d0[1]}, [r0, :32], r1
|
||||
.else
|
||||
vst1.16 {d1}, [r0, :64], r1
|
||||
.endif
|
||||
.endif
|
||||
|
||||
// Reset pri_taps and directions back to the original point
|
||||
sub r5, r5, #2
|
||||
.if \pri
|
||||
sub r8, r8, #2
|
||||
.endif
|
||||
|
||||
bgt 1b
|
||||
vpop {q4-q7}
|
||||
pop {r4-r9,pc}
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
.macro filter w, bpc
|
||||
filter_func \w, \bpc, pri=1, sec=0, min=0, suffix=_pri
|
||||
filter_func \w, \bpc, pri=0, sec=1, min=0, suffix=_sec
|
||||
filter_func \w, \bpc, pri=1, sec=1, min=1, suffix=_pri_sec
|
||||
|
||||
function cdef_filter\w\()_\bpc\()bpc_neon, export=1
|
||||
push {r4-r9,lr}
|
||||
vpush {q4-q7}
|
||||
ldrd r4, r5, [sp, #92]
|
||||
ldrd r6, r7, [sp, #100]
|
||||
.if \bpc == 16
|
||||
ldrd r8, r9, [sp, #108]
|
||||
.else
|
||||
ldr r8, [sp, #108]
|
||||
.endif
|
||||
cmp r3, #0 // pri_strength
|
||||
bne 1f
|
||||
b cdef_filter\w\()_sec_\bpc\()bpc_neon // only sec
|
||||
1:
|
||||
cmp r4, #0 // sec_strength
|
||||
bne 1f
|
||||
b cdef_filter\w\()_pri_\bpc\()bpc_neon // only pri
|
||||
1:
|
||||
b cdef_filter\w\()_pri_sec_\bpc\()bpc_neon // both pri and sec
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
const div_table, align=4
|
||||
.short 840, 420, 280, 210, 168, 140, 120, 105
|
||||
endconst
|
||||
|
||||
const alt_fact, align=4
|
||||
.short 420, 210, 140, 105, 105, 105, 105, 105, 140, 210, 420, 0
|
||||
endconst
|
||||
|
||||
.macro cost_alt dest, s1, s2, s3, s4, s5, s6
|
||||
vmull.s16 q1, \s1, \s1 // sum_alt[n]*sum_alt[n]
|
||||
vmull.s16 q2, \s2, \s2
|
||||
vmull.s16 q3, \s3, \s3
|
||||
vmull.s16 q5, \s4, \s4 // sum_alt[n]*sum_alt[n]
|
||||
vmull.s16 q12, \s5, \s5
|
||||
vmull.s16 q6, \s6, \s6 // q6 overlaps the first \s1-\s2 here
|
||||
vmul.i32 q1, q1, q13 // sum_alt[n]^2*fact
|
||||
vmla.i32 q1, q2, q14
|
||||
vmla.i32 q1, q3, q15
|
||||
vmul.i32 q5, q5, q13 // sum_alt[n]^2*fact
|
||||
vmla.i32 q5, q12, q14
|
||||
vmla.i32 q5, q6, q15
|
||||
vadd.i32 d2, d2, d3
|
||||
vadd.i32 d3, d10, d11
|
||||
vpadd.i32 \dest, d2, d3 // *cost_ptr
|
||||
.endm
|
||||
|
||||
.macro find_best s1, s2, s3
|
||||
.ifnb \s2
|
||||
vmov.32 lr, \s2
|
||||
.endif
|
||||
cmp r12, r1 // cost[n] > best_cost
|
||||
itt gt
|
||||
movgt r0, r3 // best_dir = n
|
||||
movgt r1, r12 // best_cost = cost[n]
|
||||
.ifnb \s2
|
||||
add r3, r3, #1 // n++
|
||||
cmp lr, r1 // cost[n] > best_cost
|
||||
vmov.32 r12, \s3
|
||||
itt gt
|
||||
movgt r0, r3 // best_dir = n
|
||||
movgt r1, lr // best_cost = cost[n]
|
||||
add r3, r3, #1 // n++
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// int dav1d_cdef_find_dir_Xbpc_neon(const pixel *img, const ptrdiff_t stride,
|
||||
// unsigned *const var)
|
||||
.macro find_dir bpc
|
||||
function cdef_find_dir_\bpc\()bpc_neon, export=1
|
||||
push {lr}
|
||||
vpush {q4-q7}
|
||||
.if \bpc == 16
|
||||
clz r3, r3 // clz(bitdepth_max)
|
||||
sub lr, r3, #24 // -bitdepth_min_8
|
||||
.endif
|
||||
sub sp, sp, #32 // cost
|
||||
mov r3, #8
|
||||
vmov.u16 q1, #0 // q0-q1 sum_diag[0]
|
||||
vmov.u16 q3, #0 // q2-q3 sum_diag[1]
|
||||
vmov.u16 q5, #0 // q4-q5 sum_hv[0-1]
|
||||
vmov.u16 q8, #0 // q6,d16 sum_alt[0]
|
||||
// q7,d17 sum_alt[1]
|
||||
vmov.u16 q9, #0 // q9,d22 sum_alt[2]
|
||||
vmov.u16 q11, #0
|
||||
vmov.u16 q10, #0 // q10,d23 sum_alt[3]
|
||||
|
||||
|
||||
.irpc i, 01234567
|
||||
.if \bpc == 8
|
||||
vld1.8 {d30}, [r0, :64], r1
|
||||
vmov.u8 d31, #128
|
||||
vsubl.u8 q15, d30, d31 // img[x] - 128
|
||||
.else
|
||||
vld1.16 {q15}, [r0, :128], r1
|
||||
vdup.16 q14, lr // -bitdepth_min_8
|
||||
vshl.u16 q15, q15, q14
|
||||
vmov.u16 q14, #128
|
||||
vsub.i16 q15, q15, q14 // img[x] - 128
|
||||
.endif
|
||||
vmov.u16 q14, #0
|
||||
|
||||
.if \i == 0
|
||||
vmov q0, q15 // sum_diag[0]
|
||||
.else
|
||||
vext.8 q12, q14, q15, #(16-2*\i)
|
||||
vext.8 q13, q15, q14, #(16-2*\i)
|
||||
vadd.i16 q0, q0, q12 // sum_diag[0]
|
||||
vadd.i16 q1, q1, q13 // sum_diag[0]
|
||||
.endif
|
||||
vrev64.16 q13, q15
|
||||
vswp d26, d27 // [-x]
|
||||
.if \i == 0
|
||||
vmov q2, q13 // sum_diag[1]
|
||||
.else
|
||||
vext.8 q12, q14, q13, #(16-2*\i)
|
||||
vext.8 q13, q13, q14, #(16-2*\i)
|
||||
vadd.i16 q2, q2, q12 // sum_diag[1]
|
||||
vadd.i16 q3, q3, q13 // sum_diag[1]
|
||||
.endif
|
||||
|
||||
vpadd.u16 d26, d30, d31 // [(x >> 1)]
|
||||
vmov.u16 d27, #0
|
||||
vpadd.u16 d24, d26, d28
|
||||
vpadd.u16 d24, d24, d28 // [y]
|
||||
vmov.u16 r12, d24[0]
|
||||
vadd.i16 q5, q5, q15 // sum_hv[1]
|
||||
.if \i < 4
|
||||
vmov.16 d8[\i], r12 // sum_hv[0]
|
||||
.else
|
||||
vmov.16 d9[\i-4], r12 // sum_hv[0]
|
||||
.endif
|
||||
|
||||
.if \i == 0
|
||||
vmov.u16 q6, q13 // sum_alt[0]
|
||||
.else
|
||||
vext.8 q12, q14, q13, #(16-2*\i)
|
||||
vext.8 q14, q13, q14, #(16-2*\i)
|
||||
vadd.i16 q6, q6, q12 // sum_alt[0]
|
||||
vadd.i16 d16, d16, d28 // sum_alt[0]
|
||||
.endif
|
||||
vrev64.16 d26, d26 // [-(x >> 1)]
|
||||
vmov.u16 q14, #0
|
||||
.if \i == 0
|
||||
vmov q7, q13 // sum_alt[1]
|
||||
.else
|
||||
vext.8 q12, q14, q13, #(16-2*\i)
|
||||
vext.8 q13, q13, q14, #(16-2*\i)
|
||||
vadd.i16 q7, q7, q12 // sum_alt[1]
|
||||
vadd.i16 d17, d17, d26 // sum_alt[1]
|
||||
.endif
|
||||
|
||||
.if \i < 6
|
||||
vext.8 q12, q14, q15, #(16-2*(3-(\i/2)))
|
||||
vext.8 q13, q15, q14, #(16-2*(3-(\i/2)))
|
||||
vadd.i16 q9, q9, q12 // sum_alt[2]
|
||||
vadd.i16 d22, d22, d26 // sum_alt[2]
|
||||
.else
|
||||
vadd.i16 q9, q9, q15 // sum_alt[2]
|
||||
.endif
|
||||
.if \i == 0
|
||||
vmov q10, q15 // sum_alt[3]
|
||||
.elseif \i == 1
|
||||
vadd.i16 q10, q10, q15 // sum_alt[3]
|
||||
.else
|
||||
vext.8 q12, q14, q15, #(16-2*(\i/2))
|
||||
vext.8 q13, q15, q14, #(16-2*(\i/2))
|
||||
vadd.i16 q10, q10, q12 // sum_alt[3]
|
||||
vadd.i16 d23, d23, d26 // sum_alt[3]
|
||||
.endif
|
||||
.endr
|
||||
|
||||
vmov.u32 q15, #105
|
||||
|
||||
vmull.s16 q12, d8, d8 // sum_hv[0]*sum_hv[0]
|
||||
vmlal.s16 q12, d9, d9
|
||||
vmull.s16 q13, d10, d10 // sum_hv[1]*sum_hv[1]
|
||||
vmlal.s16 q13, d11, d11
|
||||
vadd.s32 d8, d24, d25
|
||||
vadd.s32 d9, d26, d27
|
||||
vpadd.s32 d8, d8, d9 // cost[2,6] (s16, s17)
|
||||
vmul.i32 d8, d8, d30 // cost[2,6] *= 105
|
||||
|
||||
vrev64.16 q1, q1
|
||||
vrev64.16 q3, q3
|
||||
vext.8 q1, q1, q1, #10 // sum_diag[0][14-n]
|
||||
vext.8 q3, q3, q3, #10 // sum_diag[1][14-n]
|
||||
|
||||
vstr s16, [sp, #2*4] // cost[2]
|
||||
vstr s17, [sp, #6*4] // cost[6]
|
||||
|
||||
movrel_local r12, div_table
|
||||
vld1.16 {q14}, [r12, :128]
|
||||
|
||||
vmull.s16 q5, d0, d0 // sum_diag[0]*sum_diag[0]
|
||||
vmull.s16 q12, d1, d1
|
||||
vmlal.s16 q5, d2, d2
|
||||
vmlal.s16 q12, d3, d3
|
||||
vmull.s16 q0, d4, d4 // sum_diag[1]*sum_diag[1]
|
||||
vmull.s16 q1, d5, d5
|
||||
vmlal.s16 q0, d6, d6
|
||||
vmlal.s16 q1, d7, d7
|
||||
vmovl.u16 q13, d28 // div_table
|
||||
vmovl.u16 q14, d29
|
||||
vmul.i32 q5, q5, q13 // cost[0]
|
||||
vmla.i32 q5, q12, q14
|
||||
vmul.i32 q0, q0, q13 // cost[4]
|
||||
vmla.i32 q0, q1, q14
|
||||
vadd.i32 d10, d10, d11
|
||||
vadd.i32 d0, d0, d1
|
||||
vpadd.i32 d0, d10, d0 // cost[0,4] = s0,s1
|
||||
|
||||
movrel_local r12, alt_fact
|
||||
vld1.16 {d29, d30, d31}, [r12, :64] // div_table[2*m+1] + 105
|
||||
|
||||
vstr s0, [sp, #0*4] // cost[0]
|
||||
vstr s1, [sp, #4*4] // cost[4]
|
||||
|
||||
vmovl.u16 q13, d29 // div_table[2*m+1] + 105
|
||||
vmovl.u16 q14, d30
|
||||
vmovl.u16 q15, d31
|
||||
|
||||
cost_alt d14, d12, d13, d16, d14, d15, d17 // cost[1], cost[3]
|
||||
cost_alt d15, d18, d19, d22, d20, d21, d23 // cost[5], cost[7]
|
||||
vstr s28, [sp, #1*4] // cost[1]
|
||||
vstr s29, [sp, #3*4] // cost[3]
|
||||
|
||||
mov r0, #0 // best_dir
|
||||
vmov.32 r1, d0[0] // best_cost
|
||||
mov r3, #1 // n
|
||||
|
||||
vstr s30, [sp, #5*4] // cost[5]
|
||||
vstr s31, [sp, #7*4] // cost[7]
|
||||
|
||||
vmov.32 r12, d14[0]
|
||||
|
||||
find_best d14[0], d8[0], d14[1]
|
||||
find_best d14[1], d0[1], d15[0]
|
||||
find_best d15[0], d8[1], d15[1]
|
||||
find_best d15[1]
|
||||
|
||||
eor r3, r0, #4 // best_dir ^4
|
||||
ldr r12, [sp, r3, lsl #2]
|
||||
sub r1, r1, r12 // best_cost - cost[best_dir ^ 4]
|
||||
lsr r1, r1, #10
|
||||
str r1, [r2] // *var
|
||||
|
||||
add sp, sp, #32
|
||||
vpop {q4-q7}
|
||||
pop {pc}
|
||||
endfunc
|
||||
.endm
|
||||
2039
media/libdav1d/src/src/arm/32/filmgrain.S
Normal file
2039
media/libdav1d/src/src/arm/32/filmgrain.S
Normal file
File diff suppressed because it is too large
Load diff
2137
media/libdav1d/src/src/arm/32/filmgrain16.S
Normal file
2137
media/libdav1d/src/src/arm/32/filmgrain16.S
Normal file
File diff suppressed because it is too large
Load diff
2958
media/libdav1d/src/src/arm/32/ipred.S
Normal file
2958
media/libdav1d/src/src/arm/32/ipred.S
Normal file
File diff suppressed because it is too large
Load diff
3276
media/libdav1d/src/src/arm/32/ipred16.S
Normal file
3276
media/libdav1d/src/src/arm/32/ipred16.S
Normal file
File diff suppressed because it is too large
Load diff
3368
media/libdav1d/src/src/arm/32/itx.S
Normal file
3368
media/libdav1d/src/src/arm/32/itx.S
Normal file
File diff suppressed because it is too large
Load diff
3632
media/libdav1d/src/src/arm/32/itx16.S
Normal file
3632
media/libdav1d/src/src/arm/32/itx16.S
Normal file
File diff suppressed because it is too large
Load diff
868
media/libdav1d/src/src/arm/32/loopfilter.S
Normal file
868
media/libdav1d/src/src/arm/32/loopfilter.S
Normal file
|
|
@ -0,0 +1,868 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2019, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
.macro loop_filter wd
|
||||
function lpf_8_wd\wd\()_neon
|
||||
vabd.u8 d0, d22, d23 // abs(p1 - p0)
|
||||
vabd.u8 d1, d25, d24 // abs(q1 - q0)
|
||||
vabd.u8 d2, d23, d24 // abs(p0 - q0)
|
||||
vabd.u8 d3, d22, d25 // abs(p1 - q1)
|
||||
.if \wd >= 6
|
||||
vabd.u8 d4, d21, d22 // abs(p2 - p1)
|
||||
vabd.u8 d5, d26, d25 // abs(q2 - q1)
|
||||
.endif
|
||||
.if \wd >= 8
|
||||
vabd.u8 d6, d20, d21 // abs(p3 - p2)
|
||||
vabd.u8 d7, d27, d26 // abs(q3 - q3)
|
||||
.endif
|
||||
.if \wd >= 6
|
||||
vmax.u8 d4, d4, d5
|
||||
.endif
|
||||
vqadd.u8 d2, d2, d2 // abs(p0 - q0) * 2
|
||||
.if \wd >= 8
|
||||
vmax.u8 d6, d6, d7
|
||||
.endif
|
||||
vshr.u8 d3, d3, #1
|
||||
.if \wd >= 8
|
||||
vmax.u8 d4, d4, d6
|
||||
.endif
|
||||
.if \wd >= 6
|
||||
vand d4, d4, d14
|
||||
.endif
|
||||
vmax.u8 d0, d0, d1 // max(abs(p1 - p0), abs(q1 - q0))
|
||||
vqadd.u8 d2, d2, d3 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1
|
||||
.if \wd >= 6
|
||||
vmax.u8 d4, d0, d4
|
||||
vcge.u8 d1, d11, d4 // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I
|
||||
.else
|
||||
vcge.u8 d1, d11, d0 // max(abs(p1 - p0), abs(q1 - q0)) <= I
|
||||
.endif
|
||||
vcge.u8 d2, d10, d2 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E
|
||||
vand d1, d1, d2 // fm
|
||||
vand d1, d1, d13 // fm && wd >= 4
|
||||
.if \wd >= 6
|
||||
vand d14, d14, d1 // fm && wd > 4
|
||||
.endif
|
||||
.if \wd >= 16
|
||||
vand d15, d15, d1 // fm && wd == 16
|
||||
.endif
|
||||
|
||||
vmov r10, r11, d1
|
||||
orrs r10, r10, r11
|
||||
beq 9f // if (!fm || wd < 4) return;
|
||||
|
||||
.if \wd >= 6
|
||||
vmov.i8 d10, #1
|
||||
vabd.u8 d2, d21, d23 // abs(p2 - p0)
|
||||
vabd.u8 d3, d22, d23 // abs(p1 - p0)
|
||||
vabd.u8 d4, d25, d24 // abs(q1 - q0)
|
||||
vabd.u8 d5, d26, d24 // abs(q2 - q0)
|
||||
.if \wd >= 8
|
||||
vabd.u8 d6, d20, d23 // abs(p3 - p0)
|
||||
vabd.u8 d7, d27, d24 // abs(q3 - q0)
|
||||
.endif
|
||||
vmax.u8 d2, d2, d3
|
||||
vmax.u8 d4, d4, d5
|
||||
.if \wd >= 8
|
||||
vmax.u8 d6, d6, d7
|
||||
.endif
|
||||
vmax.u8 d2, d2, d4
|
||||
.if \wd >= 8
|
||||
vmax.u8 d2, d2, d6
|
||||
.endif
|
||||
|
||||
.if \wd == 16
|
||||
vabd.u8 d3, d17, d23 // abs(p6 - p0)
|
||||
vabd.u8 d4, d18, d23 // abs(p5 - p0)
|
||||
vabd.u8 d5, d19, d23 // abs(p4 - p0)
|
||||
.endif
|
||||
vcge.u8 d2, d10, d2 // flat8in
|
||||
.if \wd == 16
|
||||
vabd.u8 d6, d28, d24 // abs(q4 - q0)
|
||||
vabd.u8 d7, d29, d24 // abs(q5 - q0)
|
||||
vabd.u8 d8, d30, d24 // abs(q6 - q0)
|
||||
.endif
|
||||
vand d14, d2, d14 // flat8in && fm && wd > 4
|
||||
vbic d1, d1, d14 // fm && wd >= 4 && !flat8in
|
||||
.if \wd == 16
|
||||
vmax.u8 d3, d3, d4
|
||||
vmax.u8 d5, d5, d6
|
||||
.endif
|
||||
vmov r10, r11, d1
|
||||
.if \wd == 16
|
||||
vmax.u8 d7, d7, d8
|
||||
vmax.u8 d3, d3, d5
|
||||
vmax.u8 d3, d3, d7
|
||||
vcge.u8 d3, d10, d3 // flat8out
|
||||
.endif
|
||||
orrs r10, r10, r11
|
||||
.if \wd == 16
|
||||
vand d15, d15, d3 // flat8out && fm && wd == 16
|
||||
vand d15, d15, d14 // flat8out && flat8in && fm && wd == 16
|
||||
vbic d14, d14, d15 // flat8in && fm && wd >= 4 && !flat8out
|
||||
.endif
|
||||
beq 1f // skip wd == 4 case
|
||||
.endif
|
||||
|
||||
vsubl.u8 q1, d22, d25 // p1 - q1
|
||||
vcgt.u8 d0, d0, d12 // hev
|
||||
vqmovn.s16 d2, q1
|
||||
vand d4, d2, d0 // if (hev) iclip_diff(p1 - q1)
|
||||
vbic d0, d1, d0 // (fm && wd >= 4 && !hev)
|
||||
vsubl.u8 q1, d24, d23
|
||||
vmov.i16 q3, #3
|
||||
vmul.i16 q1, q1, q3
|
||||
vmov.i8 d6, #4
|
||||
vaddw.s8 q1, q1, d4
|
||||
vmov.i8 d7, #3
|
||||
vqmovn.s16 d2, q1 // f
|
||||
vqadd.s8 d4, d6, d2 // imin(f + 4, 127)
|
||||
vqadd.s8 d5, d7, d2 // imin(f + 3, 127)
|
||||
vshr.s8 d4, d4, #3 // f1
|
||||
vshr.s8 d5, d5, #3 // f2
|
||||
vmovl.u8 q1, d23 // p0
|
||||
vmovl.u8 q3, d24 // q0
|
||||
vaddw.s8 q1, q1, d5
|
||||
vsubw.s8 q3, q3, d4
|
||||
vrshr.s8 d4, d4, #1 // (f1 + 1) >> 1
|
||||
vqmovun.s16 d2, q1 // out p0
|
||||
vqmovun.s16 d6, q3 // out q0
|
||||
vbit d23, d2, d1 // if (fm && wd >= 4)
|
||||
vmovl.u8 q1, d22 // p1
|
||||
vbit d24, d6, d1 // if (fm && wd >= 4)
|
||||
vmovl.u8 q3, d25 // q1
|
||||
vaddw.s8 q1, q1, d4
|
||||
vsubw.s8 q3, q3, d4
|
||||
vqmovun.s16 d2, q1 // out p1
|
||||
vqmovun.s16 d6, q3 // out q1
|
||||
vbit d22, d2, d0 // if (fm && wd >= 4 && !hev)
|
||||
vbit d25, d6, d0 // if (fm && wd >= 4 && !hev)
|
||||
1:
|
||||
|
||||
.if \wd == 6
|
||||
vmov r10, r11, d14
|
||||
orrs r10, r10, r11
|
||||
beq 2f // skip if there's no flat8in
|
||||
|
||||
vaddl.u8 q0, d21, d21 // p2 * 2
|
||||
vaddl.u8 q1, d21, d22 // p2 + p1
|
||||
vaddl.u8 q2, d22, d23 // p1 + p0
|
||||
vaddl.u8 q3, d23, d24 // p0 + q0
|
||||
vadd.i16 q4, q0, q1
|
||||
vadd.i16 q5, q2, q3
|
||||
vaddl.u8 q6, d24, d25 // q0 + q1
|
||||
vadd.i16 q4, q4, q5
|
||||
vsub.i16 q6, q6, q0
|
||||
vaddl.u8 q5, d25, d26 // q1 + q2
|
||||
vrshrn.i16 d0, q4, #3 // out p1
|
||||
|
||||
vadd.i16 q4, q4, q6
|
||||
vsub.i16 q5, q5, q1
|
||||
vaddl.u8 q6, d26, d26 // q2 + q2
|
||||
vrshrn.i16 d1, q4, #3 // out p0
|
||||
|
||||
vadd.i16 q4, q4, q5
|
||||
vsub.i16 q6, q6, q2
|
||||
vrshrn.i16 d2, q4, #3 // out q0
|
||||
|
||||
vbit d22, d0, d14 // p1 if (flat8in)
|
||||
vadd.i16 q4, q4, q6
|
||||
vbit d23, d1, d14 // p0 if (flat8in)
|
||||
vrshrn.i16 d3, q4, #3 // out q1
|
||||
vbit d24, d2, d14 // q0 if (flat8in)
|
||||
vbit d25, d3, d14 // q1 if (flat8in)
|
||||
.elseif \wd >= 8
|
||||
vmov r10, r11, d14
|
||||
orrs r10, r10, r11
|
||||
.if \wd == 8
|
||||
beq 8f // skip if there's no flat8in
|
||||
.else
|
||||
beq 2f // skip if there's no flat8in
|
||||
.endif
|
||||
|
||||
vaddl.u8 q0, d20, d21 // p3 + p2
|
||||
vaddl.u8 q1, d22, d25 // p1 + q1
|
||||
vaddl.u8 q2, d20, d22 // p3 + p1
|
||||
vaddl.u8 q3, d23, d26 // p0 + q2
|
||||
vadd.i16 q4, q0, q0 // 2 * (p3 + p2)
|
||||
vaddw.u8 q4, q4, d23 // + p0
|
||||
vaddw.u8 q4, q4, d24 // + q0
|
||||
vadd.i16 q4, q4, q2 // + p3 + p1
|
||||
vsub.i16 q1, q1, q0 // p1 + q1 - p3 - p2
|
||||
vsub.i16 q3, q3, q2 // p0 + q2 - p3 - p1
|
||||
vrshrn.i16 d10, q4, #3 // out p2
|
||||
|
||||
vadd.i16 q4, q4, q1
|
||||
vaddl.u8 q0, d20, d23 // p3 + p0
|
||||
vaddl.u8 q1, d24, d27 // q0 + q3
|
||||
vrshrn.i16 d11, q4, #3 // out p1
|
||||
|
||||
vadd.i16 q4, q4, q3
|
||||
vsub.i16 q1, q1, q0 // q0 + q3 - p3 - p0
|
||||
vaddl.u8 q2, d21, d24 // p2 + q0
|
||||
vaddl.u8 q3, d25, d27 // q1 + q3
|
||||
vrshrn.i16 d12, q4, #3 // out p0
|
||||
|
||||
vadd.i16 q4, q4, q1
|
||||
vsub.i16 q3, q3, q2 // q1 + q3 - p2 - q0
|
||||
vaddl.u8 q0, d22, d25 // p1 + q1
|
||||
vaddl.u8 q1, d26, d27 // q2 + q3
|
||||
vrshrn.i16 d13, q4, #3 // out q0
|
||||
|
||||
vadd.i16 q4, q4, q3
|
||||
vsub.i16 q1, q1, q0 // q2 + q3 - p1 - q1
|
||||
vrshrn.i16 d0, q4, #3 // out q1
|
||||
|
||||
vadd.i16 q4, q4, q1
|
||||
|
||||
vbit d21, d10, d14
|
||||
vbit d22, d11, d14
|
||||
vbit d23, d12, d14
|
||||
vrshrn.i16 d1, q4, #3 // out q2
|
||||
vbit d24, d13, d14
|
||||
vbit d25, d0, d14
|
||||
vbit d26, d1, d14
|
||||
.endif
|
||||
2:
|
||||
.if \wd == 16
|
||||
vmov r10, r11, d15
|
||||
orrs r10, r10, r11
|
||||
bne 1f // check if flat8out is needed
|
||||
vmov r10, r11, d14
|
||||
orrs r10, r10, r11
|
||||
beq 8f // if there was no flat8in, just write the inner 4 pixels
|
||||
b 7f // if flat8in was used, write the inner 6 pixels
|
||||
1:
|
||||
|
||||
vaddl.u8 q1, d17, d17 // p6 + p6
|
||||
vaddl.u8 q2, d17, d18 // p6 + p5
|
||||
vaddl.u8 q3, d17, d19 // p6 + p4
|
||||
vaddl.u8 q4, d17, d20 // p6 + p3
|
||||
vadd.i16 q6, q1, q2
|
||||
vadd.i16 q5, q3, q4
|
||||
vaddl.u8 q3, d17, d21 // p6 + p2
|
||||
vadd.i16 q6, q6, q5
|
||||
vaddl.u8 q4, d17, d22 // p6 + p1
|
||||
vaddl.u8 q5, d18, d23 // p5 + p0
|
||||
vadd.i16 q3, q3, q4
|
||||
vaddl.u8 q4, d19, d24 // p4 + q0
|
||||
vadd.i16 q6, q6, q3
|
||||
vadd.i16 q5, q5, q4
|
||||
vaddl.u8 q3, d20, d25 // p3 + q1
|
||||
vadd.i16 q6, q6, q5
|
||||
vsub.i16 q3, q3, q1
|
||||
vaddl.u8 q1, d21, d26 // p2 + q2
|
||||
vrshrn.i16 d0, q6, #4 // out p5
|
||||
vadd.i16 q6, q6, q3 // - (p6 + p6) + (p3 + q1)
|
||||
vsub.i16 q1, q1, q2
|
||||
vaddl.u8 q2, d22, d27 // p1 + q3
|
||||
vaddl.u8 q3, d17, d19 // p6 + p4
|
||||
vrshrn.i16 d1, q6, #4 // out p4
|
||||
vadd.i16 q6, q6, q1 // - (p6 + p5) + (p2 + q2)
|
||||
vsub.i16 q2, q2, q3
|
||||
vaddl.u8 q3, d23, d28 // p0 + q4
|
||||
vaddl.u8 q4, d17, d20 // p6 + p3
|
||||
vrshrn.i16 d2, q6, #4 // out p3
|
||||
vadd.i16 q6, q6, q2 // - (p6 + p4) + (p1 + q3)
|
||||
vsub.i16 q3, q3, q4
|
||||
vaddl.u8 q4, d24, d29 // q0 + q5
|
||||
vaddl.u8 q2, d17, d21 // p6 + p2
|
||||
vrshrn.i16 d3, q6, #4 // out p2
|
||||
vadd.i16 q6, q6, q3 // - (p6 + p3) + (p0 + q4)
|
||||
vsub.i16 q4, q4, q2
|
||||
vaddl.u8 q3, d25, d30 // q1 + q6
|
||||
vaddl.u8 q5, d17, d22 // p6 + p1
|
||||
vrshrn.i16 d4, q6, #4 // out p1
|
||||
vadd.i16 q6, q6, q4 // - (p6 + p2) + (q0 + q5)
|
||||
vsub.i16 q3, q3, q5
|
||||
vaddl.u8 q4, d26, d30 // q2 + q6
|
||||
vbif d0, d18, d15 // out p5
|
||||
vaddl.u8 q5, d18, d23 // p5 + p0
|
||||
vrshrn.i16 d5, q6, #4 // out p0
|
||||
vadd.i16 q6, q6, q3 // - (p6 + p1) + (q1 + q6)
|
||||
vsub.i16 q4, q4, q5
|
||||
vaddl.u8 q5, d27, d30 // q3 + q6
|
||||
vbif d1, d19, d15 // out p4
|
||||
vaddl.u8 q9, d19, d24 // p4 + q0
|
||||
vrshrn.i16 d6, q6, #4 // out q0
|
||||
vadd.i16 q6, q6, q4 // - (p5 + p0) + (q2 + q6)
|
||||
vsub.i16 q5, q5, q9
|
||||
vaddl.u8 q4, d28, d30 // q4 + q6
|
||||
vbif d2, d20, d15 // out p3
|
||||
vaddl.u8 q9, d20, d25 // p3 + q1
|
||||
vrshrn.i16 d7, q6, #4 // out q1
|
||||
vadd.i16 q6, q6, q5 // - (p4 + q0) + (q3 + q6)
|
||||
vsub.i16 q9, q4, q9
|
||||
vaddl.u8 q5, d29, d30 // q5 + q6
|
||||
vbif d3, d21, d15 // out p2
|
||||
vaddl.u8 q10, d21, d26 // p2 + q2
|
||||
vrshrn.i16 d8, q6, #4 // out q2
|
||||
vadd.i16 q6, q6, q9 // - (p3 + q1) + (q4 + q6)
|
||||
vsub.i16 q5, q5, q10
|
||||
vaddl.u8 q9, d30, d30 // q6 + q6
|
||||
vbif d4, d22, d15 // out p1
|
||||
vaddl.u8 q10, d22, d27 // p1 + q3
|
||||
vrshrn.i16 d9, q6, #4 // out q3
|
||||
vadd.i16 q6, q6, q5 // - (p2 + q2) + (q5 + q6)
|
||||
vsub.i16 q9, q9, q10
|
||||
vbif d5, d23, d15 // out p0
|
||||
vrshrn.i16 d10, q6, #4 // out q4
|
||||
vadd.i16 q6, q6, q9 // - (p1 + q3) + (q6 + q6)
|
||||
vrshrn.i16 d11, q6, #4 // out q5
|
||||
vbif d6, d24, d15 // out q0
|
||||
vbif d7, d25, d15 // out q1
|
||||
vbif d8, d26, d15 // out q2
|
||||
vbif d9, d27, d15 // out q3
|
||||
vbif d10, d28, d15 // out q4
|
||||
vbif d11, d29, d15 // out q5
|
||||
.endif
|
||||
|
||||
bx lr
|
||||
.if \wd == 16
|
||||
7:
|
||||
// Return to a shorter epilogue, writing only the inner 6 pixels
|
||||
bx r8
|
||||
.endif
|
||||
.if \wd >= 8
|
||||
8:
|
||||
// Return to a shorter epilogue, writing only the inner 4 pixels
|
||||
bx r9
|
||||
.endif
|
||||
9:
|
||||
// Return directly without writing back any pixels
|
||||
bx r12
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
loop_filter 16
|
||||
loop_filter 8
|
||||
loop_filter 6
|
||||
loop_filter 4
|
||||
|
||||
.macro lpf_8_wd16
|
||||
adr r8, 7f + CONFIG_THUMB
|
||||
adr r9, 8f + CONFIG_THUMB
|
||||
bl lpf_8_wd16_neon
|
||||
.endm
|
||||
|
||||
.macro lpf_8_wd8
|
||||
adr r9, 8f + CONFIG_THUMB
|
||||
bl lpf_8_wd8_neon
|
||||
.endm
|
||||
|
||||
.macro lpf_8_wd6
|
||||
bl lpf_8_wd6_neon
|
||||
.endm
|
||||
|
||||
.macro lpf_8_wd4
|
||||
bl lpf_8_wd4_neon
|
||||
.endm
|
||||
|
||||
function lpf_v_4_8_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, r1, lsl #1
|
||||
vld1.8 {d22}, [r10, :64], r1 // p1
|
||||
vld1.8 {d24}, [r0, :64], r1 // q0
|
||||
vld1.8 {d23}, [r10, :64], r1 // p0
|
||||
vld1.8 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
|
||||
lpf_8_wd4
|
||||
|
||||
sub r10, r0, r1, lsl #1
|
||||
vst1.8 {d22}, [r10, :64], r1 // p1
|
||||
vst1.8 {d24}, [r0, :64], r1 // q0
|
||||
vst1.8 {d23}, [r10, :64], r1 // p0
|
||||
vst1.8 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_h_4_8_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, #2
|
||||
add r0, r10, r1, lsl #2
|
||||
vld1.32 {d22[0]}, [r10], r1
|
||||
vld1.32 {d22[1]}, [r0], r1
|
||||
vld1.32 {d23[0]}, [r10], r1
|
||||
vld1.32 {d23[1]}, [r0], r1
|
||||
vld1.32 {d24[0]}, [r10], r1
|
||||
vld1.32 {d24[1]}, [r0], r1
|
||||
vld1.32 {d25[0]}, [r10], r1
|
||||
vld1.32 {d25[1]}, [r0], r1
|
||||
add r0, r0, #2
|
||||
|
||||
transpose_4x8b q11, q12, d22, d23, d24, d25
|
||||
|
||||
lpf_8_wd4
|
||||
|
||||
sub r10, r0, r1, lsl #3
|
||||
sub r10, r10, #2
|
||||
transpose_4x8b q11, q12, d22, d23, d24, d25
|
||||
add r0, r10, r1, lsl #2
|
||||
|
||||
vst1.32 {d22[0]}, [r10], r1
|
||||
vst1.32 {d22[1]}, [r0], r1
|
||||
vst1.32 {d23[0]}, [r10], r1
|
||||
vst1.32 {d23[1]}, [r0], r1
|
||||
vst1.32 {d24[0]}, [r10], r1
|
||||
vst1.32 {d24[1]}, [r0], r1
|
||||
vst1.32 {d25[0]}, [r10], r1
|
||||
vst1.32 {d25[1]}, [r0], r1
|
||||
add r0, r0, #2
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_v_6_8_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, r1, lsl #1
|
||||
sub r10, r10, r1
|
||||
vld1.8 {d21}, [r10, :64], r1 // p2
|
||||
vld1.8 {d24}, [r0, :64], r1 // q0
|
||||
vld1.8 {d22}, [r10, :64], r1 // p1
|
||||
vld1.8 {d25}, [r0, :64], r1 // q1
|
||||
vld1.8 {d23}, [r10, :64], r1 // p0
|
||||
vld1.8 {d26}, [r0, :64], r1 // q2
|
||||
sub r0, r0, r1, lsl #1
|
||||
sub r0, r0, r1
|
||||
|
||||
lpf_8_wd6
|
||||
|
||||
sub r10, r0, r1, lsl #1
|
||||
vst1.8 {d22}, [r10, :64], r1 // p1
|
||||
vst1.8 {d24}, [r0, :64], r1 // q0
|
||||
vst1.8 {d23}, [r10, :64], r1 // p0
|
||||
vst1.8 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_h_6_8_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, #4
|
||||
add r0, r10, r1, lsl #2
|
||||
vld1.8 {d20}, [r10], r1
|
||||
vld1.8 {d24}, [r0], r1
|
||||
vld1.8 {d21}, [r10], r1
|
||||
vld1.8 {d25}, [r0], r1
|
||||
vld1.8 {d22}, [r10], r1
|
||||
vld1.8 {d26}, [r0], r1
|
||||
vld1.8 {d23}, [r10], r1
|
||||
vld1.8 {d27}, [r0], r1
|
||||
add r0, r0, #4
|
||||
|
||||
transpose_8x8b q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
|
||||
|
||||
lpf_8_wd6
|
||||
|
||||
sub r10, r0, r1, lsl #3
|
||||
sub r10, r10, #2
|
||||
transpose_4x8b q11, q12, d22, d23, d24, d25
|
||||
add r0, r10, r1, lsl #2
|
||||
|
||||
vst1.32 {d22[0]}, [r10], r1
|
||||
vst1.32 {d22[1]}, [r0], r1
|
||||
vst1.32 {d23[0]}, [r10], r1
|
||||
vst1.32 {d23[1]}, [r0], r1
|
||||
vst1.32 {d24[0]}, [r10], r1
|
||||
vst1.32 {d24[1]}, [r0], r1
|
||||
vst1.32 {d25[0]}, [r10], r1
|
||||
vst1.32 {d25[1]}, [r0], r1
|
||||
add r0, r0, #2
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_v_8_8_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, r1, lsl #2
|
||||
vld1.8 {d20}, [r10, :64], r1 // p3
|
||||
vld1.8 {d24}, [r0, :64], r1 // q0
|
||||
vld1.8 {d21}, [r10, :64], r1 // p2
|
||||
vld1.8 {d25}, [r0, :64], r1 // q1
|
||||
vld1.8 {d22}, [r10, :64], r1 // p1
|
||||
vld1.8 {d26}, [r0, :64], r1 // q2
|
||||
vld1.8 {d23}, [r10, :64], r1 // p0
|
||||
vld1.8 {d27}, [r0, :64], r1 // q3
|
||||
sub r0, r0, r1, lsl #2
|
||||
|
||||
lpf_8_wd8
|
||||
|
||||
sub r10, r0, r1, lsl #1
|
||||
sub r10, r10, r1
|
||||
vst1.8 {d21}, [r10, :64], r1 // p2
|
||||
vst1.8 {d24}, [r0, :64], r1 // q0
|
||||
vst1.8 {d22}, [r10, :64], r1 // p1
|
||||
vst1.8 {d25}, [r0, :64], r1 // q1
|
||||
vst1.8 {d23}, [r10, :64], r1 // p0
|
||||
vst1.8 {d26}, [r0, :64], r1 // q2
|
||||
sub r0, r0, r1, lsl #1
|
||||
sub r0, r0, r1
|
||||
bx r12
|
||||
|
||||
8:
|
||||
sub r10, r0, r1, lsl #1
|
||||
vst1.8 {d22}, [r10, :64], r1 // p1
|
||||
vst1.8 {d24}, [r0, :64], r1 // q0
|
||||
vst1.8 {d23}, [r10, :64], r1 // p0
|
||||
vst1.8 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_h_8_8_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, #4
|
||||
add r0, r10, r1, lsl #2
|
||||
vld1.8 {d20}, [r10], r1
|
||||
vld1.8 {d24}, [r0], r1
|
||||
vld1.8 {d21}, [r10], r1
|
||||
vld1.8 {d25}, [r0], r1
|
||||
vld1.8 {d22}, [r10], r1
|
||||
vld1.8 {d26}, [r0], r1
|
||||
vld1.8 {d23}, [r10], r1
|
||||
vld1.8 {d27}, [r0], r1
|
||||
add r0, r0, #4
|
||||
|
||||
transpose_8x8b q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
|
||||
|
||||
lpf_8_wd8
|
||||
|
||||
sub r10, r0, r1, lsl #3
|
||||
sub r10, r10, #4
|
||||
transpose_8x8b q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
|
||||
add r0, r10, r1, lsl #2
|
||||
|
||||
vst1.8 {d20}, [r10], r1
|
||||
vst1.8 {d24}, [r0], r1
|
||||
vst1.8 {d21}, [r10], r1
|
||||
vst1.8 {d25}, [r0], r1
|
||||
vst1.8 {d22}, [r10], r1
|
||||
vst1.8 {d26}, [r0], r1
|
||||
vst1.8 {d23}, [r10], r1
|
||||
vst1.8 {d27}, [r0], r1
|
||||
add r0, r0, #4
|
||||
bx r12
|
||||
8:
|
||||
sub r10, r0, r1, lsl #3
|
||||
sub r10, r10, #2
|
||||
transpose_4x8b q11, q12, d22, d23, d24, d25
|
||||
add r0, r10, r1, lsl #2
|
||||
|
||||
vst1.32 {d22[0]}, [r10], r1
|
||||
vst1.32 {d22[1]}, [r0], r1
|
||||
vst1.32 {d23[0]}, [r10], r1
|
||||
vst1.32 {d23[1]}, [r0], r1
|
||||
vst1.32 {d24[0]}, [r10], r1
|
||||
vst1.32 {d24[1]}, [r0], r1
|
||||
vst1.32 {d25[0]}, [r10], r1
|
||||
vst1.32 {d25[1]}, [r0], r1
|
||||
add r0, r0, #2
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_v_16_8_neon
|
||||
mov r12, lr
|
||||
|
||||
sub r10, r0, r1, lsl #3
|
||||
add r10, r10, r1
|
||||
vld1.8 {d17}, [r10, :64], r1 // p6
|
||||
vld1.8 {d24}, [r0, :64], r1 // q0
|
||||
vld1.8 {d18}, [r10, :64], r1 // p5
|
||||
vld1.8 {d25}, [r0, :64], r1 // q1
|
||||
vld1.8 {d19}, [r10, :64], r1 // p4
|
||||
vld1.8 {d26}, [r0, :64], r1 // q2
|
||||
vld1.8 {d20}, [r10, :64], r1 // p3
|
||||
vld1.8 {d27}, [r0, :64], r1 // q3
|
||||
vld1.8 {d21}, [r10, :64], r1 // p2
|
||||
vld1.8 {d28}, [r0, :64], r1 // q4
|
||||
vld1.8 {d22}, [r10, :64], r1 // p1
|
||||
vld1.8 {d29}, [r0, :64], r1 // q5
|
||||
vld1.8 {d23}, [r10, :64], r1 // p0
|
||||
vld1.8 {d30}, [r0, :64], r1 // q6
|
||||
sub r0, r0, r1, lsl #3
|
||||
add r0, r0, r1
|
||||
|
||||
lpf_8_wd16
|
||||
|
||||
sub r10, r0, r1, lsl #2
|
||||
sub r10, r10, r1, lsl #1
|
||||
vst1.8 {d0}, [r10, :64], r1 // p5
|
||||
vst1.8 {d6}, [r0, :64], r1 // q0
|
||||
vst1.8 {d1}, [r10, :64], r1 // p4
|
||||
vst1.8 {d7}, [r0, :64], r1 // q1
|
||||
vst1.8 {d2}, [r10, :64], r1 // p3
|
||||
vst1.8 {d8}, [r0, :64], r1 // q2
|
||||
vst1.8 {d3}, [r10, :64], r1 // p2
|
||||
vst1.8 {d9}, [r0, :64], r1 // q3
|
||||
vst1.8 {d4}, [r10, :64], r1 // p1
|
||||
vst1.8 {d10}, [r0, :64], r1 // q4
|
||||
vst1.8 {d5}, [r10, :64], r1 // p0
|
||||
vst1.8 {d11}, [r0, :64], r1 // q5
|
||||
sub r0, r0, r1, lsl #2
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
7:
|
||||
sub r10, r0, r1
|
||||
sub r10, r10, r1, lsl #1
|
||||
vst1.8 {d21}, [r10, :64], r1 // p2
|
||||
vst1.8 {d24}, [r0, :64], r1 // q0
|
||||
vst1.8 {d22}, [r10, :64], r1 // p1
|
||||
vst1.8 {d25}, [r0, :64], r1 // q1
|
||||
vst1.8 {d23}, [r10, :64], r1 // p0
|
||||
vst1.8 {d26}, [r0, :64], r1 // q2
|
||||
sub r0, r0, r1, lsl #1
|
||||
sub r0, r0, r1
|
||||
bx r12
|
||||
|
||||
8:
|
||||
sub r10, r0, r1, lsl #1
|
||||
vst1.8 {d22}, [r10, :64], r1 // p1
|
||||
vst1.8 {d24}, [r0, :64], r1 // q0
|
||||
vst1.8 {d23}, [r10, :64], r1 // p0
|
||||
vst1.8 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_h_16_8_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, #8
|
||||
vld1.8 {d16}, [r10, :64], r1
|
||||
vld1.8 {d24}, [r0, :64], r1
|
||||
vld1.8 {d17}, [r10, :64], r1
|
||||
vld1.8 {d25}, [r0, :64], r1
|
||||
vld1.8 {d18}, [r10, :64], r1
|
||||
vld1.8 {d26}, [r0, :64], r1
|
||||
vld1.8 {d19}, [r10, :64], r1
|
||||
vld1.8 {d27}, [r0, :64], r1
|
||||
vld1.8 {d20}, [r10, :64], r1
|
||||
vld1.8 {d28}, [r0, :64], r1
|
||||
vld1.8 {d21}, [r10, :64], r1
|
||||
vld1.8 {d29}, [r0, :64], r1
|
||||
vld1.8 {d22}, [r10, :64], r1
|
||||
vld1.8 {d30}, [r0, :64], r1
|
||||
vld1.8 {d23}, [r10, :64], r1
|
||||
vld1.8 {d31}, [r0, :64], r1
|
||||
|
||||
transpose_8x8b q8, q9, q10, q11, d16, d17, d18, d19, d20, d21, d22, d23
|
||||
transpose_8x8b q12, q13, q14, q15, d24, d25, d26, d27, d28, d29, d30, d31
|
||||
|
||||
lpf_8_wd16
|
||||
|
||||
sub r0, r0, r1, lsl #3
|
||||
sub r10, r0, #8
|
||||
|
||||
transpose_8x8b q8, q0, q1, q2, d16, d17, d0, d1, d2, d3, d4, d5
|
||||
transpose_8x8b q3, q4, q5, q15, d6, d7, d8, d9, d10, d11, d30, d31
|
||||
|
||||
vst1.8 {d16}, [r10, :64], r1
|
||||
vst1.8 {d6}, [r0, :64], r1
|
||||
vst1.8 {d17}, [r10, :64], r1
|
||||
vst1.8 {d7}, [r0, :64], r1
|
||||
vst1.8 {d0}, [r10, :64], r1
|
||||
vst1.8 {d8}, [r0, :64], r1
|
||||
vst1.8 {d1}, [r10, :64], r1
|
||||
vst1.8 {d9}, [r0, :64], r1
|
||||
vst1.8 {d2}, [r10, :64], r1
|
||||
vst1.8 {d10}, [r0, :64], r1
|
||||
vst1.8 {d3}, [r10, :64], r1
|
||||
vst1.8 {d11}, [r0, :64], r1
|
||||
vst1.8 {d4}, [r10, :64], r1
|
||||
vst1.8 {d30}, [r0, :64], r1
|
||||
vst1.8 {d5}, [r10, :64], r1
|
||||
vst1.8 {d31}, [r0, :64], r1
|
||||
bx r12
|
||||
|
||||
7:
|
||||
sub r10, r0, r1, lsl #3
|
||||
sub r10, r10, #4
|
||||
transpose_8x8b q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
|
||||
add r0, r10, r1, lsl #2
|
||||
|
||||
vst1.8 {d20}, [r10], r1
|
||||
vst1.8 {d24}, [r0], r1
|
||||
vst1.8 {d21}, [r10], r1
|
||||
vst1.8 {d25}, [r0], r1
|
||||
vst1.8 {d22}, [r10], r1
|
||||
vst1.8 {d26}, [r0], r1
|
||||
vst1.8 {d23}, [r10], r1
|
||||
vst1.8 {d27}, [r0], r1
|
||||
add r0, r0, #4
|
||||
bx r12
|
||||
8:
|
||||
sub r10, r0, r1, lsl #3
|
||||
sub r10, r10, #2
|
||||
transpose_4x8b q11, q12, d22, d23, d24, d25
|
||||
add r0, r10, r1, lsl #2
|
||||
|
||||
vst1.32 {d22[0]}, [r10], r1
|
||||
vst1.32 {d22[1]}, [r0], r1
|
||||
vst1.32 {d23[0]}, [r10], r1
|
||||
vst1.32 {d23[1]}, [r0], r1
|
||||
vst1.32 {d24[0]}, [r10], r1
|
||||
vst1.32 {d24[1]}, [r0], r1
|
||||
vst1.32 {d25[0]}, [r10], r1
|
||||
vst1.32 {d25[1]}, [r0], r1
|
||||
add r0, r0, #2
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
// void dav1d_lpf_v_sb_y_8bpc_neon(pixel *dst, const ptrdiff_t stride,
|
||||
// const uint32_t *const vmask,
|
||||
// const uint8_t (*l)[4], ptrdiff_t b4_stride,
|
||||
// const Av1FilterLUT *lut, const int w)
|
||||
|
||||
.macro lpf_func dir, type
|
||||
function lpf_\dir\()_sb_\type\()_8bpc_neon, export=1
|
||||
push {r4-r11,lr}
|
||||
vpush {q4-q7}
|
||||
ldrd r4, r5, [sp, #100]
|
||||
ldrd r6, r7, [r2] // vmask[0], vmask[1]
|
||||
.ifc \type, y
|
||||
ldr r2, [r2, #8] // vmask[2]
|
||||
.endif
|
||||
add r5, r5, #128 // Move to sharp part of lut
|
||||
.ifc \type, y
|
||||
orr r7, r7, r2 // vmask[1] |= vmask[2]
|
||||
.endif
|
||||
.ifc \dir, v
|
||||
sub r4, r3, r4, lsl #2
|
||||
.else
|
||||
sub r3, r3, #4
|
||||
lsl r4, r4, #2
|
||||
.endif
|
||||
orr r6, r6, r7 // vmask[0] |= vmask[1]
|
||||
|
||||
1:
|
||||
tst r6, #0x03
|
||||
.ifc \dir, v
|
||||
vld1.8 {d0}, [r4]!
|
||||
vld1.8 {d1}, [r3]!
|
||||
.else
|
||||
vld2.32 {d0[0], d1[0]}, [r3], r4
|
||||
vld2.32 {d0[1], d1[1]}, [r3], r4
|
||||
.endif
|
||||
beq 7f // if (!(vm & bits)) continue;
|
||||
|
||||
vld1.8 {d5[]}, [r5] // sharp[0]
|
||||
add r5, r5, #8
|
||||
vmov.i32 d2, #0xff
|
||||
vdup.32 d13, r6 // vmask[0]
|
||||
|
||||
vand d0, d0, d2 // Keep only lowest byte in each 32 bit word
|
||||
vand d1, d1, d2
|
||||
vtst.8 d3, d1, d2 // Check for nonzero values in l[0][0]
|
||||
vmov.i8 d4, #1
|
||||
vld1.8 {d6[]}, [r5] // sharp[1]
|
||||
sub r5, r5, #8
|
||||
vbif d1, d0, d3 // if (!l[0][0]) L = l[offset][0]
|
||||
vtst.32 d2, d1, d2 // L != 0
|
||||
vmul.i32 d1, d1, d4 // L
|
||||
.ifc \type, y
|
||||
vdup.32 d15, r2 // vmask[2]
|
||||
.endif
|
||||
vdup.32 d14, r7 // vmask[1]
|
||||
vmov r10, r11, d2
|
||||
orrs r10, r10, r11
|
||||
beq 7f // if (!L) continue;
|
||||
vneg.s8 d5, d5 // -sharp[0]
|
||||
movrel_local r10, word_12
|
||||
vshr.u8 d12, d1, #4 // H
|
||||
vld1.32 {d16}, [r10, :64]
|
||||
vshl.s8 d3, d1, d5 // L >> sharp[0]
|
||||
.ifc \type, y
|
||||
vtst.32 d15, d15, d16 // if (vmask[2] & bits)
|
||||
.endif
|
||||
vmov.i8 d7, #2
|
||||
vmin.u8 d3, d3, d6 // imin(L >> sharp[0], sharp[1])
|
||||
vadd.i8 d0, d1, d7 // L + 2
|
||||
vmax.u8 d11, d3, d4 // imax(imin(), 1) = limit = I
|
||||
vadd.u8 d0, d0, d0 // 2*(L + 2)
|
||||
vtst.32 d14, d14, d16 // if (vmask[1] & bits)
|
||||
vadd.i8 d10, d0, d11 // 2*(L + 2) + limit = E
|
||||
vtst.32 d13, d13, d16 // if (vmask[0] & bits)
|
||||
vand d13, d13, d2 // vmask[0] &= L != 0
|
||||
|
||||
.ifc \type, y
|
||||
tst r2, #0x03
|
||||
beq 2f
|
||||
// wd16
|
||||
bl lpf_\dir\()_16_8_neon
|
||||
b 8f
|
||||
2:
|
||||
.endif
|
||||
tst r7, #0x03
|
||||
beq 3f
|
||||
.ifc \type, y
|
||||
// wd8
|
||||
bl lpf_\dir\()_8_8_neon
|
||||
.else
|
||||
// wd6
|
||||
bl lpf_\dir\()_6_8_neon
|
||||
.endif
|
||||
b 8f
|
||||
3:
|
||||
// wd4
|
||||
bl lpf_\dir\()_4_8_neon
|
||||
.ifc \dir, h
|
||||
b 8f
|
||||
7:
|
||||
// For dir h, the functions above increment r0.
|
||||
// If the whole function is skipped, increment it here instead.
|
||||
add r0, r0, r1, lsl #3
|
||||
.else
|
||||
7:
|
||||
.endif
|
||||
8:
|
||||
lsrs r6, r6, #2 // vmask[0] >>= 2
|
||||
lsr r7, r7, #2 // vmask[1] >>= 2
|
||||
.ifc \type, y
|
||||
lsr r2, r2, #2 // vmask[2] >>= 2
|
||||
.endif
|
||||
.ifc \dir, v
|
||||
add r0, r0, #8
|
||||
.else
|
||||
// For dir h, r0 is returned incremented
|
||||
.endif
|
||||
bne 1b
|
||||
|
||||
vpop {q4-q7}
|
||||
pop {r4-r11,pc}
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
lpf_func v, y
|
||||
lpf_func h, y
|
||||
lpf_func v, uv
|
||||
lpf_func h, uv
|
||||
|
||||
const word_12, align=4
|
||||
.word 1, 2
|
||||
endconst
|
||||
859
media/libdav1d/src/src/arm/32/loopfilter16.S
Normal file
859
media/libdav1d/src/src/arm/32/loopfilter16.S
Normal file
|
|
@ -0,0 +1,859 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2020, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
.macro loop_filter wd
|
||||
function lpf_4_wd\wd\()_neon
|
||||
vabd.u16 d0, d22, d23 // abs(p1 - p0)
|
||||
vabd.u16 d1, d25, d24 // abs(q1 - q0)
|
||||
vabd.u16 d2, d23, d24 // abs(p0 - q0)
|
||||
vabd.u16 d3, d22, d25 // abs(p1 - q1)
|
||||
.if \wd >= 6
|
||||
vabd.u16 d4, d21, d22 // abs(p2 - p1)
|
||||
vabd.u16 d5, d26, d25 // abs(q2 - q1)
|
||||
.endif
|
||||
.if \wd >= 8
|
||||
vabd.u16 d6, d20, d21 // abs(p3 - p2)
|
||||
vabd.u16 d7, d27, d26 // abs(q3 - q3)
|
||||
.endif
|
||||
.if \wd >= 6
|
||||
vmax.u16 d4, d4, d5
|
||||
.endif
|
||||
vqadd.u16 d2, d2, d2 // abs(p0 - q0) * 2
|
||||
.if \wd >= 8
|
||||
vmax.u16 d6, d6, d7
|
||||
.endif
|
||||
vshr.u16 d3, d3, #1
|
||||
.if \wd >= 8
|
||||
vmax.u16 d4, d4, d6
|
||||
.endif
|
||||
vmax.u16 d0, d0, d1 // max(abs(p1 - p0), abs(q1 - q0))
|
||||
vqadd.u16 d2, d2, d3 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1
|
||||
.if \wd >= 6
|
||||
vmax.u16 d4, d0, d4
|
||||
vcge.u16 d1, d11, d4 // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I
|
||||
.else
|
||||
vcge.u16 d1, d11, d0 // max(abs(p1 - p0), abs(q1 - q0)) <= I
|
||||
.endif
|
||||
vcge.u16 d2, d10, d2 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E
|
||||
vand d1, d1, d2 // fm && wd >= 4 (implicit)
|
||||
.if \wd >= 6
|
||||
vmov d14, d1 // fm && wd > 4 (implicit)
|
||||
.endif
|
||||
.if \wd >= 16
|
||||
vmov d15, d1 // fm && wd == 16 (implicit)
|
||||
.endif
|
||||
|
||||
vmov r10, r11, d1
|
||||
orrs r10, r10, r11
|
||||
beq 9f // if (!fm || wd < 4) return;
|
||||
|
||||
.if \wd >= 6
|
||||
vmov.i16 d10, #1
|
||||
vabd.u16 d2, d21, d23 // abs(p2 - p0)
|
||||
vabd.u16 d3, d22, d23 // abs(p1 - p0)
|
||||
vabd.u16 d4, d25, d24 // abs(q1 - q0)
|
||||
vabd.u16 d5, d26, d24 // abs(q2 - q0)
|
||||
vdup.16 d9, r9 // bitdepth_min_8
|
||||
.if \wd >= 8
|
||||
vabd.u16 d6, d20, d23 // abs(p3 - p0)
|
||||
vabd.u16 d7, d27, d24 // abs(q3 - q0)
|
||||
.endif
|
||||
vmax.u16 d2, d2, d3
|
||||
vmax.u16 d4, d4, d5
|
||||
.if \wd >= 8
|
||||
vmax.u16 d6, d6, d7
|
||||
.endif
|
||||
vmax.u16 d2, d2, d4
|
||||
vshl.u16 d10, d10, d9 // F = 1 << bitdepth_min_8
|
||||
.if \wd >= 8
|
||||
vmax.u16 d2, d2, d6
|
||||
.endif
|
||||
|
||||
.if \wd == 16
|
||||
vabd.u16 d3, d17, d23 // abs(p6 - p0)
|
||||
vabd.u16 d4, d18, d23 // abs(p5 - p0)
|
||||
vabd.u16 d5, d19, d23 // abs(p4 - p0)
|
||||
.endif
|
||||
vcge.u16 d2, d10, d2 // flat8in
|
||||
.if \wd == 16
|
||||
vabd.u16 d6, d28, d24 // abs(q4 - q0)
|
||||
vabd.u16 d7, d29, d24 // abs(q5 - q0)
|
||||
vabd.u16 d8, d30, d24 // abs(q6 - q0)
|
||||
.endif
|
||||
vand d14, d2, d14 // flat8in && fm && wd > 4
|
||||
vbic d1, d1, d14 // fm && wd >= 4 && !flat8in
|
||||
.if \wd == 16
|
||||
vmax.u16 d3, d3, d4
|
||||
vmax.u16 d5, d5, d6
|
||||
.endif
|
||||
vmov r10, r11, d1
|
||||
.if \wd == 16
|
||||
vmax.u16 d7, d7, d8
|
||||
vmax.u16 d3, d3, d5
|
||||
vmax.u16 d3, d3, d7
|
||||
vcge.u16 d3, d10, d3 // flat8out
|
||||
.endif
|
||||
orrs r10, r10, r11
|
||||
.if \wd == 16
|
||||
vand d15, d15, d3 // flat8out && fm && wd == 16
|
||||
vand d15, d15, d14 // flat8out && flat8in && fm && wd == 16
|
||||
vbic d14, d14, d15 // flat8in && fm && wd >= 4 && !flat8out
|
||||
.endif
|
||||
beq 1f // skip wd == 4 case
|
||||
.endif
|
||||
|
||||
vdup.16 d3, r8 // bitdepth_max
|
||||
vsub.u16 d2, d22, d25 // p1 - q1
|
||||
vshr.u16 d3, d3, #1 // 128 << bitdepth_min_8 - 1
|
||||
vcgt.u16 d0, d0, d12 // hev
|
||||
vmvn d9, d3 // - 128 * (1 << bitdepth_min_8)
|
||||
vmin.s16 d2, d2, d3 // iclip_diff(p1 - q1)
|
||||
vmax.s16 d2, d2, d9 // iclip_diff(p1 - q1)
|
||||
vand d4, d2, d0 // if (hev) iclip_diff(p1 - q1)
|
||||
vsub.u16 d2, d24, d23
|
||||
vmov.i16 d6, #3
|
||||
vbic d0, d1, d0 // (fm && wd >= 4 && !hev)
|
||||
vmul.i16 d2, d2, d6
|
||||
vmov.i16 d7, #4
|
||||
vadd.i16 d2, d2, d4
|
||||
vmin.s16 d2, d2, d3 // f = iclip_diff()
|
||||
vmax.s16 d2, d2, d9 // f = iclip_diff()
|
||||
vqadd.s16 d4, d7, d2 // f + 4
|
||||
vqadd.s16 d5, d6, d2 // f + 3
|
||||
vmin.s16 d4, d4, d3 // imin(f + 4, 128 << bitdepth_min_8 - 1)
|
||||
vmin.s16 d5, d5, d3 // imin(f + 3, 128 << bitdepth_min_8 - 1)
|
||||
vshr.s16 d4, d4, #3 // f1
|
||||
vshr.s16 d5, d5, #3 // f2
|
||||
vmov.i16 d9, #0
|
||||
vdup.16 d3, r8 // bitdepth_max
|
||||
vqadd.s16 d2, d23, d5 // p0 + f2
|
||||
vqsub.s16 d6, d24, d4 // q0 - f1
|
||||
vrshr.s16 d4, d4, #1 // (f1 + 1) >> 1
|
||||
vmin.s16 d2, d2, d3 // out p0 = iclip_pixel()
|
||||
vmin.s16 d6, d6, d3 // out q0 = iclip_pixel()
|
||||
vmax.s16 d2, d2, d9 // out p0 = iclip_pixel()
|
||||
vmax.s16 d6, d6, d9 // out q0 = iclip_pixel()
|
||||
vbit d23, d2, d1 // if (fm && wd >= 4)
|
||||
vbit d24, d6, d1 // if (fm && wd >= 4)
|
||||
vqadd.s16 d2, d22, d4 // p1 + f
|
||||
vqsub.s16 d6, d25, d4 // q1 - f
|
||||
vmin.s16 d2, d2, d3 // out p1 = iclip_pixel()
|
||||
vmin.s16 d6, d6, d3 // out q1 = iclip_pixel()
|
||||
vmax.s16 d2, d2, d9 // out p1 = iclip_pixel()
|
||||
vmax.s16 d6, d6, d9 // out q1 = iclip_pixel()
|
||||
vbit d22, d2, d0 // if (fm && wd >= 4 && !hev)
|
||||
vbit d25, d6, d0 // if (fm && wd >= 4 && !hev)
|
||||
1:
|
||||
|
||||
.if \wd == 6
|
||||
vmov r10, r11, d14
|
||||
orrs r10, r10, r11
|
||||
beq 2f // skip if there's no flat8in
|
||||
|
||||
vadd.i16 d0, d21, d21 // p2 * 2
|
||||
vadd.i16 d2, d21, d22 // p2 + p1
|
||||
vadd.i16 d4, d22, d23 // p1 + p0
|
||||
vadd.i16 d6, d23, d24 // p0 + q0
|
||||
vadd.i16 d8, d0, d2
|
||||
vadd.i16 d10, d4, d6
|
||||
vadd.i16 d12, d24, d25 // q0 + q1
|
||||
vadd.i16 d8, d8, d10
|
||||
vsub.i16 d12, d12, d0
|
||||
vadd.i16 d10, d25, d26 // q1 + q2
|
||||
vrshr.u16 d0, d8, #3 // out p1
|
||||
|
||||
vadd.i16 d8, d8, d12
|
||||
vsub.i16 d10, d10, d2
|
||||
vadd.i16 d12, d26, d26 // q2 + q2
|
||||
vrshr.u16 d1, d8, #3 // out p0
|
||||
|
||||
vadd.i16 d8, d8, d10
|
||||
vsub.i16 d12, d12, d4
|
||||
vrshr.u16 d2, d8, #3 // out q0
|
||||
|
||||
vbit d22, d0, d14 // p1 if (flat8in)
|
||||
vadd.i16 d8, d8, d12
|
||||
vbit d23, d1, d14 // p0 if (flat8in)
|
||||
vrshr.u16 d3, d8, #3 // out q1
|
||||
vbit d24, d2, d14 // q0 if (flat8in)
|
||||
vbit d25, d3, d14 // q1 if (flat8in)
|
||||
.elseif \wd >= 8
|
||||
vmov r10, r11, d14
|
||||
orrs r10, r10, r11
|
||||
.if \wd == 8
|
||||
beq 8f // skip if there's no flat8in
|
||||
.else
|
||||
beq 2f // skip if there's no flat8in
|
||||
.endif
|
||||
|
||||
vadd.i16 d0, d20, d21 // p3 + p2
|
||||
vadd.i16 d2, d22, d25 // p1 + q1
|
||||
vadd.i16 d4, d20, d22 // p3 + p1
|
||||
vadd.i16 d6, d23, d26 // p0 + q2
|
||||
vadd.i16 d8, d0, d0 // 2 * (p3 + p2)
|
||||
vadd.i16 d9, d23, d24 // p0 + q0
|
||||
vadd.i16 d8, d8, d4 // + p3 + p1
|
||||
vsub.i16 d2, d2, d0 // p1 + q1 - p3 - p2
|
||||
vadd.i16 d8, d8, d9 // + p0 + q0
|
||||
vsub.i16 d6, d6, d4 // p0 + q2 - p3 - p1
|
||||
vrshr.u16 d10, d8, #3 // out p2
|
||||
|
||||
vadd.i16 d8, d8, d2
|
||||
vadd.i16 d0, d20, d23 // p3 + p0
|
||||
vadd.i16 d2, d24, d27 // q0 + q3
|
||||
vrshr.u16 d11, d8, #3 // out p1
|
||||
|
||||
vadd.i16 d8, d8, d6
|
||||
vsub.i16 d2, d2, d0 // q0 + q3 - p3 - p0
|
||||
vadd.i16 d4, d21, d24 // p2 + q0
|
||||
vadd.i16 d6, d25, d27 // q1 + q3
|
||||
vrshr.u16 d12, d8, #3 // out p0
|
||||
|
||||
vadd.i16 d8, d8, d2
|
||||
vsub.i16 d6, d6, d4 // q1 + q3 - p2 - q0
|
||||
vadd.i16 d0, d22, d25 // p1 + q1
|
||||
vadd.i16 d2, d26, d27 // q2 + q3
|
||||
vrshr.u16 d13, d8, #3 // out q0
|
||||
|
||||
vadd.i16 d8, d8, d6
|
||||
vsub.i16 d2, d2, d0 // q2 + q3 - p1 - q1
|
||||
vrshr.u16 d0, d8, #3 // out q1
|
||||
|
||||
vadd.i16 d8, d8, d2
|
||||
|
||||
vbit d21, d10, d14
|
||||
vbit d22, d11, d14
|
||||
vbit d23, d12, d14
|
||||
vrshr.u16 d1, d8, #3 // out q2
|
||||
vbit d24, d13, d14
|
||||
vbit d25, d0, d14
|
||||
vbit d26, d1, d14
|
||||
.endif
|
||||
2:
|
||||
.if \wd == 16
|
||||
vmov r10, r11, d15
|
||||
orrs r10, r10, r11
|
||||
bne 1f // check if flat8out is needed
|
||||
vmov r10, r11, d14
|
||||
orrs r10, r10, r11
|
||||
beq 8f // if there was no flat8in, just write the inner 4 pixels
|
||||
b 7f // if flat8in was used, write the inner 6 pixels
|
||||
1:
|
||||
|
||||
vadd.i16 d2, d17, d17 // p6 + p6
|
||||
vadd.i16 d4, d17, d18 // p6 + p5
|
||||
vadd.i16 d6, d17, d19 // p6 + p4
|
||||
vadd.i16 d8, d17, d20 // p6 + p3
|
||||
vadd.i16 d12, d2, d4
|
||||
vadd.i16 d10, d6, d8
|
||||
vadd.i16 d6, d17, d21 // p6 + p2
|
||||
vadd.i16 d12, d12, d10
|
||||
vadd.i16 d8, d17, d22 // p6 + p1
|
||||
vadd.i16 d10, d18, d23 // p5 + p0
|
||||
vadd.i16 d6, d6, d8
|
||||
vadd.i16 d8, d19, d24 // p4 + q0
|
||||
vadd.i16 d12, d12, d6
|
||||
vadd.i16 d10, d10, d8
|
||||
vadd.i16 d6, d20, d25 // p3 + q1
|
||||
vadd.i16 d12, d12, d10
|
||||
vsub.i16 d6, d6, d2
|
||||
vadd.i16 d2, d21, d26 // p2 + q2
|
||||
vrshr.u16 d0, d12, #4 // out p5
|
||||
vadd.i16 d12, d12, d6 // - (p6 + p6) + (p3 + q1)
|
||||
vsub.i16 d2, d2, d4
|
||||
vadd.i16 d4, d22, d27 // p1 + q3
|
||||
vadd.i16 d6, d17, d19 // p6 + p4
|
||||
vrshr.u16 d1, d12, #4 // out p4
|
||||
vadd.i16 d12, d12, d2 // - (p6 + p5) + (p2 + q2)
|
||||
vsub.i16 d4, d4, d6
|
||||
vadd.i16 d6, d23, d28 // p0 + q4
|
||||
vadd.i16 d8, d17, d20 // p6 + p3
|
||||
vrshr.u16 d2, d12, #4 // out p3
|
||||
vadd.i16 d12, d12, d4 // - (p6 + p4) + (p1 + q3)
|
||||
vsub.i16 d6, d6, d8
|
||||
vadd.i16 d8, d24, d29 // q0 + q5
|
||||
vadd.i16 d4, d17, d21 // p6 + p2
|
||||
vrshr.u16 d3, d12, #4 // out p2
|
||||
vadd.i16 d12, d12, d6 // - (p6 + p3) + (p0 + q4)
|
||||
vsub.i16 d8, d8, d4
|
||||
vadd.i16 d6, d25, d30 // q1 + q6
|
||||
vadd.i16 d10, d17, d22 // p6 + p1
|
||||
vrshr.u16 d4, d12, #4 // out p1
|
||||
vadd.i16 d12, d12, d8 // - (p6 + p2) + (q0 + q5)
|
||||
vsub.i16 d6, d6, d10
|
||||
vadd.i16 d8, d26, d30 // q2 + q6
|
||||
vbif d0, d18, d15 // out p5
|
||||
vadd.i16 d10, d18, d23 // p5 + p0
|
||||
vrshr.u16 d5, d12, #4 // out p0
|
||||
vadd.i16 d12, d12, d6 // - (p6 + p1) + (q1 + q6)
|
||||
vsub.i16 d8, d8, d10
|
||||
vadd.i16 d10, d27, d30 // q3 + q6
|
||||
vbif d1, d19, d15 // out p4
|
||||
vadd.i16 d18, d19, d24 // p4 + q0
|
||||
vrshr.u16 d6, d12, #4 // out q0
|
||||
vadd.i16 d12, d12, d8 // - (p5 + p0) + (q2 + q6)
|
||||
vsub.i16 d10, d10, d18
|
||||
vadd.i16 d8, d28, d30 // q4 + q6
|
||||
vbif d2, d20, d15 // out p3
|
||||
vadd.i16 d18, d20, d25 // p3 + q1
|
||||
vrshr.u16 d7, d12, #4 // out q1
|
||||
vadd.i16 d12, d12, d10 // - (p4 + q0) + (q3 + q6)
|
||||
vsub.i16 d18, d8, d18
|
||||
vadd.i16 d10, d29, d30 // q5 + q6
|
||||
vbif d3, d21, d15 // out p2
|
||||
vadd.i16 d20, d21, d26 // p2 + q2
|
||||
vrshr.u16 d8, d12, #4 // out q2
|
||||
vadd.i16 d12, d12, d18 // - (p3 + q1) + (q4 + q6)
|
||||
vsub.i16 d10, d10, d20
|
||||
vadd.i16 d18, d30, d30 // q6 + q6
|
||||
vbif d4, d22, d15 // out p1
|
||||
vadd.i16 d20, d22, d27 // p1 + q3
|
||||
vrshr.u16 d9, d12, #4 // out q3
|
||||
vadd.i16 d12, d12, d10 // - (p2 + q2) + (q5 + q6)
|
||||
vsub.i16 d18, d18, d20
|
||||
vbif d5, d23, d15 // out p0
|
||||
vrshr.u16 d10, d12, #4 // out q4
|
||||
vadd.i16 d12, d12, d18 // - (p1 + q3) + (q6 + q6)
|
||||
vrshr.u16 d11, d12, #4 // out q5
|
||||
vbif d6, d24, d15 // out q0
|
||||
vbif d7, d25, d15 // out q1
|
||||
vbif d8, d26, d15 // out q2
|
||||
vbif d9, d27, d15 // out q3
|
||||
vbif d10, d28, d15 // out q4
|
||||
vbif d11, d29, d15 // out q5
|
||||
.endif
|
||||
|
||||
bx lr
|
||||
.if \wd == 16
|
||||
7:
|
||||
// Return to a shorter epilogue, writing only the inner 6 pixels
|
||||
bx r6
|
||||
.endif
|
||||
.if \wd >= 8
|
||||
8:
|
||||
// Return to a shorter epilogue, writing only the inner 4 pixels
|
||||
bx r7
|
||||
.endif
|
||||
9:
|
||||
// Return directly without writing back any pixels
|
||||
bx r12
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
loop_filter 16
|
||||
loop_filter 8
|
||||
loop_filter 6
|
||||
loop_filter 4
|
||||
|
||||
.macro lpf_4_wd16
|
||||
adr r6, 7f + CONFIG_THUMB
|
||||
adr r7, 8f + CONFIG_THUMB
|
||||
bl lpf_4_wd16_neon
|
||||
.endm
|
||||
|
||||
.macro lpf_4_wd8
|
||||
adr r7, 8f + CONFIG_THUMB
|
||||
bl lpf_4_wd8_neon
|
||||
.endm
|
||||
|
||||
.macro lpf_4_wd6
|
||||
bl lpf_4_wd6_neon
|
||||
.endm
|
||||
|
||||
.macro lpf_4_wd4
|
||||
bl lpf_4_wd4_neon
|
||||
.endm
|
||||
|
||||
function lpf_v_4_4_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, r1, lsl #1
|
||||
vld1.16 {d22}, [r10, :64], r1 // p1
|
||||
vld1.16 {d24}, [r0, :64], r1 // q0
|
||||
vld1.16 {d23}, [r10, :64], r1 // p0
|
||||
vld1.16 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
|
||||
lpf_4_wd4
|
||||
|
||||
sub r10, r0, r1, lsl #1
|
||||
vst1.16 {d22}, [r10, :64], r1 // p1
|
||||
vst1.16 {d24}, [r0, :64], r1 // q0
|
||||
vst1.16 {d23}, [r10, :64], r1 // p0
|
||||
vst1.16 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_h_4_4_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, #4
|
||||
add r0, r10, r1, lsl #1
|
||||
vld1.16 {d22}, [r10], r1
|
||||
vld1.16 {d24}, [r0], r1
|
||||
vld1.16 {d23}, [r10], r1
|
||||
vld1.16 {d25}, [r0], r1
|
||||
add r0, r0, #4
|
||||
|
||||
transpose_4x4h q11, q12, d22, d23, d24, d25
|
||||
|
||||
lpf_4_wd4
|
||||
|
||||
sub r10, r0, r1, lsl #2
|
||||
sub r10, r10, #4
|
||||
transpose_4x4h q11, q12, d22, d23, d24, d25
|
||||
add r0, r10, r1, lsl #1
|
||||
|
||||
vst1.16 {d22}, [r10], r1
|
||||
vst1.16 {d24}, [r0], r1
|
||||
vst1.16 {d23}, [r10], r1
|
||||
vst1.16 {d25}, [r0], r1
|
||||
add r0, r0, #4
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_v_6_4_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, r1, lsl #1
|
||||
sub r10, r10, r1
|
||||
vld1.16 {d21}, [r10, :64], r1 // p2
|
||||
vld1.16 {d24}, [r0, :64], r1 // q0
|
||||
vld1.16 {d22}, [r10, :64], r1 // p1
|
||||
vld1.16 {d25}, [r0, :64], r1 // q1
|
||||
vld1.16 {d23}, [r10, :64], r1 // p0
|
||||
vld1.16 {d26}, [r0, :64], r1 // q2
|
||||
sub r0, r0, r1, lsl #1
|
||||
sub r0, r0, r1
|
||||
|
||||
lpf_4_wd6
|
||||
|
||||
sub r10, r0, r1, lsl #1
|
||||
vst1.16 {d22}, [r10, :64], r1 // p1
|
||||
vst1.16 {d24}, [r0, :64], r1 // q0
|
||||
vst1.16 {d23}, [r10, :64], r1 // p0
|
||||
vst1.16 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_h_6_4_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, #8
|
||||
vld1.16 {d20}, [r10, :64], r1
|
||||
vld1.16 {d24}, [r0, :64], r1
|
||||
vld1.16 {d21}, [r10, :64], r1
|
||||
vld1.16 {d25}, [r0, :64], r1
|
||||
vld1.16 {d22}, [r10, :64], r1
|
||||
vld1.16 {d26}, [r0, :64], r1
|
||||
vld1.16 {d23}, [r10, :64], r1
|
||||
vld1.16 {d27}, [r0, :64], r1
|
||||
|
||||
transpose_4x4h q10, q11, d20, d21, d22, d23
|
||||
transpose_4x4h q12, q13, d24, d25, d26, d27
|
||||
|
||||
lpf_4_wd6
|
||||
|
||||
sub r0, r0, #4
|
||||
transpose_4x4h q11, q12, d22, d23, d24, d25
|
||||
sub r10, r0, r1, lsl #2
|
||||
sub r0, r0, r1, lsl #1
|
||||
|
||||
vst1.16 {d22}, [r10], r1
|
||||
vst1.16 {d24}, [r0], r1
|
||||
vst1.16 {d23}, [r10], r1
|
||||
vst1.16 {d25}, [r0], r1
|
||||
add r0, r0, #4
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_v_8_4_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, r1, lsl #2
|
||||
vld1.16 {d20}, [r10, :64], r1 // p3
|
||||
vld1.16 {d24}, [r0, :64], r1 // q0
|
||||
vld1.16 {d21}, [r10, :64], r1 // p2
|
||||
vld1.16 {d25}, [r0, :64], r1 // q1
|
||||
vld1.16 {d22}, [r10, :64], r1 // p1
|
||||
vld1.16 {d26}, [r0, :64], r1 // q2
|
||||
vld1.16 {d23}, [r10, :64], r1 // p0
|
||||
vld1.16 {d27}, [r0, :64], r1 // q3
|
||||
sub r0, r0, r1, lsl #2
|
||||
|
||||
lpf_4_wd8
|
||||
|
||||
sub r10, r0, r1, lsl #1
|
||||
sub r10, r10, r1
|
||||
vst1.16 {d21}, [r10, :64], r1 // p2
|
||||
vst1.16 {d24}, [r0, :64], r1 // q0
|
||||
vst1.16 {d22}, [r10, :64], r1 // p1
|
||||
vst1.16 {d25}, [r0, :64], r1 // q1
|
||||
vst1.16 {d23}, [r10, :64], r1 // p0
|
||||
vst1.16 {d26}, [r0, :64], r1 // q2
|
||||
sub r0, r0, r1, lsl #1
|
||||
sub r0, r0, r1
|
||||
bx r12
|
||||
|
||||
8:
|
||||
sub r10, r0, r1, lsl #1
|
||||
vst1.16 {d22}, [r10, :64], r1 // p1
|
||||
vst1.16 {d24}, [r0, :64], r1 // q0
|
||||
vst1.16 {d23}, [r10, :64], r1 // p0
|
||||
vst1.16 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_h_8_4_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, #8
|
||||
vld1.16 {d20}, [r10, :64], r1
|
||||
vld1.16 {d24}, [r0, :64], r1
|
||||
vld1.16 {d21}, [r10, :64], r1
|
||||
vld1.16 {d25}, [r0, :64], r1
|
||||
vld1.16 {d22}, [r10, :64], r1
|
||||
vld1.16 {d26}, [r0, :64], r1
|
||||
vld1.16 {d23}, [r10, :64], r1
|
||||
vld1.16 {d27}, [r0, :64], r1
|
||||
|
||||
transpose_4x4h q10, q11, d20, d21, d22, d23
|
||||
transpose_4x4h q12, q13, d24, d25, d26, d27
|
||||
|
||||
lpf_4_wd8
|
||||
|
||||
sub r0, r0, r1, lsl #2
|
||||
transpose_4x4h q10, q11, d20, d21, d22, d23
|
||||
transpose_4x4h q12, q13, d24, d25, d26, d27
|
||||
sub r10, r0, #8
|
||||
|
||||
vst1.16 {d20}, [r10, :64], r1
|
||||
vst1.16 {d24}, [r0, :64], r1
|
||||
vst1.16 {d21}, [r10, :64], r1
|
||||
vst1.16 {d25}, [r0, :64], r1
|
||||
vst1.16 {d22}, [r10, :64], r1
|
||||
vst1.16 {d26}, [r0, :64], r1
|
||||
vst1.16 {d23}, [r10, :64], r1
|
||||
vst1.16 {d27}, [r0, :64], r1
|
||||
bx r12
|
||||
8:
|
||||
sub r0, r0, #4
|
||||
transpose_4x4h q11, q12, d22, d23, d24, d25
|
||||
sub r10, r0, r1, lsl #2
|
||||
sub r0, r0, r1, lsl #1
|
||||
|
||||
vst1.16 {d22}, [r10], r1
|
||||
vst1.16 {d24}, [r0], r1
|
||||
vst1.16 {d23}, [r10], r1
|
||||
vst1.16 {d25}, [r0], r1
|
||||
add r0, r0, #4
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_v_16_4_neon
|
||||
mov r12, lr
|
||||
|
||||
sub r10, r0, r1, lsl #3
|
||||
add r10, r10, r1
|
||||
vld1.16 {d17}, [r10, :64], r1 // p6
|
||||
vld1.16 {d24}, [r0, :64], r1 // q0
|
||||
vld1.16 {d18}, [r10, :64], r1 // p5
|
||||
vld1.16 {d25}, [r0, :64], r1 // q1
|
||||
vld1.16 {d19}, [r10, :64], r1 // p4
|
||||
vld1.16 {d26}, [r0, :64], r1 // q2
|
||||
vld1.16 {d20}, [r10, :64], r1 // p3
|
||||
vld1.16 {d27}, [r0, :64], r1 // q3
|
||||
vld1.16 {d21}, [r10, :64], r1 // p2
|
||||
vld1.16 {d28}, [r0, :64], r1 // q4
|
||||
vld1.16 {d22}, [r10, :64], r1 // p1
|
||||
vld1.16 {d29}, [r0, :64], r1 // q5
|
||||
vld1.16 {d23}, [r10, :64], r1 // p0
|
||||
vld1.16 {d30}, [r0, :64], r1 // q6
|
||||
sub r0, r0, r1, lsl #3
|
||||
add r0, r0, r1
|
||||
|
||||
lpf_4_wd16
|
||||
|
||||
sub r10, r0, r1, lsl #2
|
||||
sub r10, r10, r1, lsl #1
|
||||
vst1.16 {d0}, [r10, :64], r1 // p5
|
||||
vst1.16 {d6}, [r0, :64], r1 // q0
|
||||
vst1.16 {d1}, [r10, :64], r1 // p4
|
||||
vst1.16 {d7}, [r0, :64], r1 // q1
|
||||
vst1.16 {d2}, [r10, :64], r1 // p3
|
||||
vst1.16 {d8}, [r0, :64], r1 // q2
|
||||
vst1.16 {d3}, [r10, :64], r1 // p2
|
||||
vst1.16 {d9}, [r0, :64], r1 // q3
|
||||
vst1.16 {d4}, [r10, :64], r1 // p1
|
||||
vst1.16 {d10}, [r0, :64], r1 // q4
|
||||
vst1.16 {d5}, [r10, :64], r1 // p0
|
||||
vst1.16 {d11}, [r0, :64], r1 // q5
|
||||
sub r0, r0, r1, lsl #2
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
7:
|
||||
sub r10, r0, r1
|
||||
sub r10, r10, r1, lsl #1
|
||||
vst1.16 {d21}, [r10, :64], r1 // p2
|
||||
vst1.16 {d24}, [r0, :64], r1 // q0
|
||||
vst1.16 {d22}, [r10, :64], r1 // p1
|
||||
vst1.16 {d25}, [r0, :64], r1 // q1
|
||||
vst1.16 {d23}, [r10, :64], r1 // p0
|
||||
vst1.16 {d26}, [r0, :64], r1 // q2
|
||||
sub r0, r0, r1, lsl #1
|
||||
sub r0, r0, r1
|
||||
bx r12
|
||||
|
||||
8:
|
||||
sub r10, r0, r1, lsl #1
|
||||
vst1.16 {d22}, [r10, :64], r1 // p1
|
||||
vst1.16 {d24}, [r0, :64], r1 // q0
|
||||
vst1.16 {d23}, [r10, :64], r1 // p0
|
||||
vst1.16 {d25}, [r0, :64], r1 // q1
|
||||
sub r0, r0, r1, lsl #1
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
function lpf_h_16_4_neon
|
||||
mov r12, lr
|
||||
sub r10, r0, #16
|
||||
sub r0, r0, #8
|
||||
vld1.16 {d16}, [r10, :64], r1
|
||||
vld1.16 {d20}, [r0, :64], r1
|
||||
vld1.16 {d17}, [r10, :64], r1
|
||||
vld1.16 {d21}, [r0, :64], r1
|
||||
vld1.16 {d18}, [r10, :64], r1
|
||||
vld1.16 {d22}, [r0, :64], r1
|
||||
vld1.16 {d19}, [r10, :64], r1
|
||||
vld1.16 {d23}, [r0, :64], r1
|
||||
sub r10, r10, r1, lsl #2
|
||||
sub r0, r0, r1, lsl #2
|
||||
add r10, r10, #16
|
||||
add r0, r0, #16
|
||||
vld1.16 {d24}, [r10, :64], r1
|
||||
vld1.16 {d28}, [r0, :64], r1
|
||||
vld1.16 {d25}, [r10, :64], r1
|
||||
vld1.16 {d29}, [r0, :64], r1
|
||||
vld1.16 {d26}, [r10, :64], r1
|
||||
vld1.16 {d30}, [r0, :64], r1
|
||||
vld1.16 {d27}, [r10, :64], r1
|
||||
vld1.16 {d31}, [r0, :64], r1
|
||||
sub r0, r0, #8
|
||||
|
||||
transpose_4x4h q8, q9, d16, d17, d18, d19
|
||||
transpose_4x4h q10, q11, d20, d21, d22, d23
|
||||
transpose_4x4h q12, q13, d24, d25, d26, d27
|
||||
transpose_4x4h q14, q15, d28, d29, d30, d31
|
||||
|
||||
lpf_4_wd16
|
||||
|
||||
sub r0, r0, r1, lsl #2
|
||||
transpose_4x4h q8, q0, d16, d17, d0, d1
|
||||
transpose_4x4h q1, q2, d2, d3, d4, d5
|
||||
transpose_4x4h q3, q4, d6, d7, d8, d9
|
||||
transpose_4x4h q5, q15, d10, d11, d30, d31
|
||||
sub r10, r0, #16
|
||||
sub r0, r0, #8
|
||||
|
||||
vst1.16 {d16}, [r10, :64], r1
|
||||
vst1.16 {d2}, [r0, :64], r1
|
||||
vst1.16 {d17}, [r10, :64], r1
|
||||
vst1.16 {d3}, [r0, :64], r1
|
||||
vst1.16 {d0}, [r10, :64], r1
|
||||
vst1.16 {d4}, [r0, :64], r1
|
||||
vst1.16 {d1}, [r10, :64], r1
|
||||
vst1.16 {d5}, [r0, :64], r1
|
||||
sub r10, r10, r1, lsl #2
|
||||
sub r0, r0, r1, lsl #2
|
||||
add r10, r10, #16
|
||||
add r0, r0, #16
|
||||
vst1.16 {d6}, [r10, :64], r1
|
||||
vst1.16 {d10}, [r0, :64], r1
|
||||
vst1.16 {d7}, [r10, :64], r1
|
||||
vst1.16 {d11}, [r0, :64], r1
|
||||
vst1.16 {d8}, [r10, :64], r1
|
||||
vst1.16 {d30}, [r0, :64], r1
|
||||
vst1.16 {d9}, [r10, :64], r1
|
||||
vst1.16 {d31}, [r0, :64], r1
|
||||
sub r0, r0, #8
|
||||
|
||||
bx r12
|
||||
|
||||
7:
|
||||
sub r0, r0, r1, lsl #2
|
||||
transpose_4x4h q10, q11, d20, d21, d22, d23
|
||||
transpose_4x4h q12, q13, d24, d25, d26, d27
|
||||
sub r10, r0, #8
|
||||
|
||||
vst1.16 {d20}, [r10, :64], r1
|
||||
vst1.16 {d24}, [r0, :64], r1
|
||||
vst1.16 {d21}, [r10, :64], r1
|
||||
vst1.16 {d25}, [r0, :64], r1
|
||||
vst1.16 {d22}, [r10, :64], r1
|
||||
vst1.16 {d26}, [r0, :64], r1
|
||||
vst1.16 {d23}, [r10, :64], r1
|
||||
vst1.16 {d27}, [r0, :64], r1
|
||||
bx r12
|
||||
8:
|
||||
sub r0, r0, #4
|
||||
transpose_4x4h q11, q12, d22, d23, d24, d25
|
||||
sub r10, r0, r1, lsl #2
|
||||
sub r0, r0, r1, lsl #1
|
||||
|
||||
vst1.16 {d22}, [r10], r1
|
||||
vst1.16 {d24}, [r0], r1
|
||||
vst1.16 {d23}, [r10], r1
|
||||
vst1.16 {d25}, [r0], r1
|
||||
add r0, r0, #4
|
||||
bx r12
|
||||
endfunc
|
||||
|
||||
// void dav1d_lpf_v_sb_y_16bpc_neon(pixel *dst, const ptrdiff_t stride,
|
||||
// const uint32_t *const vmask,
|
||||
// const uint8_t (*l)[4], ptrdiff_t b4_stride,
|
||||
// const Av1FilterLUT *lut, const int w,
|
||||
// const int bitdepth_max)
|
||||
|
||||
.macro lpf_func dir, type
|
||||
function lpf_\dir\()_sb_\type\()_16bpc_neon, export=1
|
||||
push {r4-r11,lr}
|
||||
vpush {q4-q7}
|
||||
ldrd r4, r5, [sp, #100]
|
||||
ldr r8, [sp, #112] // bitdepth_max; the 'w' parameter isn't loaded
|
||||
sub sp, sp, #8
|
||||
clz r9, r8
|
||||
rsb r9, r9, #24 // bitdepth_min_8
|
||||
ldrd r6, r7, [r2] // vmask[0], vmask[1]
|
||||
.ifc \type, y
|
||||
ldr r2, [r2, #8] // vmask[2]
|
||||
.endif
|
||||
add r5, r5, #128 // Move to sharp part of lut
|
||||
.ifc \type, y
|
||||
orr r7, r7, r2 // vmask[1] |= vmask[2]
|
||||
.endif
|
||||
.ifc \dir, v
|
||||
sub r4, r3, r4, lsl #2
|
||||
.else
|
||||
sub r3, r3, #4
|
||||
lsl r4, r4, #2
|
||||
.endif
|
||||
orr r6, r6, r7 // vmask[0] |= vmask[1]
|
||||
|
||||
1:
|
||||
tst r6, #0x01
|
||||
strd r6, r7, [sp]
|
||||
.ifc \dir, v
|
||||
ldrb r10, [r4], #4
|
||||
ldrb r11, [r3], #4
|
||||
.else
|
||||
ldrb r10, [r3]
|
||||
ldrb r11, [r3, #4]
|
||||
add r3, r3, r4
|
||||
.endif
|
||||
beq 7f // if (!(vm & bits)) continue;
|
||||
|
||||
orrs r12, r10, r11
|
||||
vdup.16 d31, r9 // bitdepth_min_8
|
||||
beq 7f // if (!(l[0][0] | l[offset][0])) continue;
|
||||
cmp r11, #0 // Check for nonzero values in l[0][0]
|
||||
ldrb r6, [r5], #8 // sharp[0]
|
||||
it eq
|
||||
moveq r11, r10 // if (!l[0][0]) L = l[offset][0]
|
||||
ldrb r12, [r5] // sharp[1]
|
||||
lsr r6, r11, r6 // L >> sharp[0]
|
||||
sub r5, r5, #8
|
||||
cmp r12, r6
|
||||
lsr r10, r11, #4 // H
|
||||
add r11, r11, #2 // L + 2
|
||||
it lt
|
||||
movlt r6, r12 // imin(L >> sharp[0], sharp[1])
|
||||
add r11, r11, r11 // 2*(L + 2)
|
||||
cmp r6, #1
|
||||
lsl r10, r10, r9 // H << bitdepth_min_8
|
||||
it lt
|
||||
movlt r6, #1 // imax(imin(), 1) = limit = I
|
||||
vdup.16 d12, r10 // H << bitdepth_min_8
|
||||
add r11, r11, r6 // 2*(L + 2) + limit = E
|
||||
lsl r6, r6, r9 // I << bitdepth_min_8
|
||||
lsl r11, r11, r9 // E << bitdepth_min_8
|
||||
vdup.16 d11, r6 // I << bitdepth_min_8
|
||||
vdup.16 d10, r11 // E << bitdepth_min_8
|
||||
|
||||
.ifc \type, y
|
||||
tst r2, #0x01
|
||||
beq 2f
|
||||
// wd16
|
||||
bl lpf_\dir\()_16_4_neon
|
||||
b 8f
|
||||
2:
|
||||
.endif
|
||||
tst r7, #0x01
|
||||
beq 3f
|
||||
.ifc \type, y
|
||||
// wd8
|
||||
bl lpf_\dir\()_8_4_neon
|
||||
.else
|
||||
// wd6
|
||||
bl lpf_\dir\()_6_4_neon
|
||||
.endif
|
||||
b 8f
|
||||
3:
|
||||
// wd4
|
||||
bl lpf_\dir\()_4_4_neon
|
||||
.ifc \dir, h
|
||||
b 8f
|
||||
7:
|
||||
// For dir h, the functions above increment r0.
|
||||
// If the whole function is skipped, increment it here instead.
|
||||
add r0, r0, r1, lsl #2
|
||||
.else
|
||||
7:
|
||||
.endif
|
||||
8:
|
||||
ldrd r6, r7, [sp]
|
||||
.ifc \type, y
|
||||
lsr r2, r2, #1 // vmask[2] >>= 1
|
||||
.endif
|
||||
.ifc \dir, v
|
||||
add r0, r0, #8
|
||||
.else
|
||||
// For dir h, r0 is returned incremented
|
||||
.endif
|
||||
lsrs r6, r6, #1 // vmask[0] >>= 1
|
||||
lsr r7, r7, #1 // vmask[1] >>= 1
|
||||
bne 1b
|
||||
|
||||
add sp, sp, #8
|
||||
vpop {q4-q7}
|
||||
pop {r4-r11,pc}
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
lpf_func v, y
|
||||
lpf_func h, y
|
||||
lpf_func v, uv
|
||||
lpf_func h, uv
|
||||
729
media/libdav1d/src/src/arm/32/looprestoration.S
Normal file
729
media/libdav1d/src/src/arm/32/looprestoration.S
Normal file
|
|
@ -0,0 +1,729 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2019, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
const right_ext_mask_buf
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
right_ext_mask:
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
endconst
|
||||
|
||||
// void dav1d_wiener_filter_h_8bpc_neon(int16_t *dst, const pixel (*left)[4],
|
||||
// const pixel *src, const int16_t fh[8],
|
||||
// const int w,
|
||||
// const enum LrEdgeFlags edges);
|
||||
function wiener_filter_h_8bpc_neon, export=1
|
||||
push {r4-r5,lr}
|
||||
ldrd r4, r5, [sp, #12]
|
||||
vld1.16 {q0}, [r3, :128]
|
||||
movw r12, #(1 << 14) - (1 << 2)
|
||||
vdup.16 q14, r12
|
||||
vmov.s16 q15, #2048
|
||||
|
||||
// Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL
|
||||
tst r5, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
// LR_HAVE_LEFT
|
||||
cmp r1, #0
|
||||
bne 0f
|
||||
// left == NULL
|
||||
sub r2, r2, #3
|
||||
vld1.8 {q2}, [r2]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.8 {q2}, [r2]!
|
||||
vld1.32 {d3[1]}, [r1]
|
||||
// Move r2 back to account for the last 3 bytes we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r2, r2, #3
|
||||
vext.8 q2, q1, q2, #13
|
||||
b 2f
|
||||
|
||||
1:
|
||||
vld1.8 {q2}, [r2]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost byte
|
||||
// and shift q2 to have 3x the first byte at the front.
|
||||
vdup.8 q1, d4[0]
|
||||
// Move r2 back to account for the last 3 bytes we loaded before,
|
||||
// which we shifted out.
|
||||
sub r2, r2, #3
|
||||
vext.8 q2, q1, q2, #13
|
||||
|
||||
2:
|
||||
vmovl.u8 q1, d4
|
||||
vmovl.u8 q2, d5
|
||||
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r4, #11
|
||||
bge 4f // If w >= 11, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 11, w+3 pixels valid in q1-q2. For w=9 or w=10,
|
||||
// this ends up called again; it's not strictly needed in those
|
||||
// cases (we pad enough here), but keeping the code as simple as possible.
|
||||
|
||||
// The padding pixel is q1/2.h[w+2]. r2 points at the next input, ie
|
||||
// q1/2.h[16]. Thus read from r2[w-14] to find the padding pixel.
|
||||
sub r12, r4, #14
|
||||
// Insert padding in q1/2.h[w+3] onwards; fuse the +3 (*2) into the
|
||||
// buffer pointer.
|
||||
movrel_local r3, right_ext_mask, -6
|
||||
ldrb r12, [r2, r12]
|
||||
sub r3, r3, r4, lsl #1
|
||||
vdup.16 q13, r12
|
||||
vld1.8 {q10, q11}, [r3]
|
||||
|
||||
vbit q1, q13, q10
|
||||
vbit q2, q13, q11
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 q10, q1, q2, #4
|
||||
vext.8 q11, q1, q2, #8
|
||||
vext.8 q9, q1, q2, #2
|
||||
vext.8 q12, q1, q2, #10
|
||||
vext.8 q13, q1, q2, #12
|
||||
vext.8 q8, q1, q2, #6
|
||||
vadd.i16 q10, q10, q11
|
||||
vadd.i16 q9, q9, q12
|
||||
vadd.i16 q13, q13, q1
|
||||
vshl.s16 q1, q8, #7
|
||||
vmul.s16 q3, q8, d0[3]
|
||||
vmla.s16 q3, q10, d1[0]
|
||||
vmla.s16 q3, q9, d1[1]
|
||||
vmla.s16 q3, q13, d1[2]
|
||||
|
||||
vsub.s16 q1, q1, q14
|
||||
vqadd.s16 q3, q3, q1
|
||||
vshr.s16 q3, q3, #3
|
||||
vadd.s16 q3, q3, q15
|
||||
subs r4, r4, #8
|
||||
vst1.16 {q3}, [r0, :128]!
|
||||
|
||||
ble 9f
|
||||
vmov q1, q2
|
||||
vld1.8 {d4}, [r2]!
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
vmovl.u8 q2, d4
|
||||
bne 4b // If we don't need to pad, just keep filtering.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
pop {r4-r5,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_wiener_filter_v_8bpc_neon(pixel *dst, int16_t **ptrs,
|
||||
// const int16_t fv[8], const int w);
|
||||
function wiener_filter_v_8bpc_neon, export=1
|
||||
push {r4-r9,lr}
|
||||
vpush {q4-q6}
|
||||
|
||||
vld1.16 {q0}, [r2, :128]
|
||||
|
||||
ldrd r4, r5, [r1]
|
||||
ldrd r6, r7, [r1, #8]
|
||||
ldrd r8, r9, [r1, #16]
|
||||
|
||||
1:
|
||||
vld1.16 {q1, q2}, [r4, :128]!
|
||||
vld1.16 {q8, q9}, [r9, :128]!
|
||||
|
||||
vld1.16 {q5, q6}, [r5, :128]!
|
||||
|
||||
vld1.16 {q10, q11}, [r6, :128]!
|
||||
vld1.16 {q12, q13}, [r8, :128]!
|
||||
|
||||
vld1.16 {q14, q15}, [r7, :128]!
|
||||
|
||||
subs r3, r3, #16
|
||||
|
||||
vadd.i16 q1, q1, q8
|
||||
vadd.i16 q2, q2, q9
|
||||
|
||||
vadd.i16 q5, q5, q8
|
||||
vadd.i16 q6, q6, q9
|
||||
|
||||
vadd.i16 q10, q10, q12
|
||||
vadd.i16 q11, q11, q13
|
||||
|
||||
vmull.s16 q3, d28, d0[3]
|
||||
vmlal.s16 q3, d2, d0[0]
|
||||
vmlal.s16 q3, d10, d0[1]
|
||||
vmlal.s16 q3, d20, d0[2]
|
||||
|
||||
vmull.s16 q4, d29, d0[3]
|
||||
vmlal.s16 q4, d3, d0[0]
|
||||
vmlal.s16 q4, d11, d0[1]
|
||||
vmlal.s16 q4, d21, d0[2]
|
||||
|
||||
vmull.s16 q8, d30, d0[3]
|
||||
vmlal.s16 q8, d4, d0[0]
|
||||
vmlal.s16 q8, d12, d0[1]
|
||||
vmlal.s16 q8, d22, d0[2]
|
||||
|
||||
vmull.s16 q9, d31, d0[3]
|
||||
vmlal.s16 q9, d5, d0[0]
|
||||
vmlal.s16 q9, d13, d0[1]
|
||||
vmlal.s16 q9, d23, d0[2]
|
||||
|
||||
vqrshrun.s32 d6, q3, #11
|
||||
vqrshrun.s32 d7, q4, #11
|
||||
vqrshrun.s32 d16, q8, #11
|
||||
vqrshrun.s32 d17, q9, #11
|
||||
vqmovun.s16 d6, q3
|
||||
vqmovun.s16 d7, q8
|
||||
vst1.8 {q3}, [r0, :128]!
|
||||
bgt 1b
|
||||
|
||||
// Shift the pointers, but only update the first 5; the 6th pointer is
|
||||
// kept as it was before (and the 7th is implicitly identical to the
|
||||
// 6th).
|
||||
ldrd r4, r5, [r1, #4]
|
||||
ldrd r6, r7, [r1, #12]
|
||||
ldr r8, [r1, #20]
|
||||
strd r4, r5, [r1]
|
||||
strd r6, r7, [r1, #8]
|
||||
str r8, [r1, #16]
|
||||
|
||||
vpop {q4-q6}
|
||||
pop {r4-r9,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_wiener_filter_hv_8bpc_neon(pixel *dst, const pixel (*left)[4],
|
||||
// const pixel *src,
|
||||
// const int16_t filter[2][8],
|
||||
// const int w,
|
||||
// const enum LrEdgeFlags edges,
|
||||
// int16_t **ptrs);
|
||||
function wiener_filter_hv_8bpc_neon, export=1
|
||||
push {r4-r11,lr}
|
||||
vpush {q4-q7}
|
||||
ldrd r4, r5, [sp, #100]
|
||||
ldr lr, [sp, #108]
|
||||
vld1.16 {q0, q1}, [r3, :128]
|
||||
movw r12, #(1 << 14) - (1 << 2)
|
||||
vdup.16 q14, r12
|
||||
vmov.s16 q15, #2048
|
||||
|
||||
ldrd r6, r7, [lr]
|
||||
ldrd r8, r9, [lr, #8]
|
||||
ldrd r10, r11, [lr, #16]
|
||||
ldr r12, [lr, #24]
|
||||
|
||||
// Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL
|
||||
tst r5, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
// LR_HAVE_LEFT
|
||||
cmp r1, #0
|
||||
bne 0f
|
||||
// left == NULL
|
||||
sub r2, r2, #3
|
||||
vld1.8 {q2}, [r2]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.8 {q2}, [r2]!
|
||||
vld1.32 {d3[1]}, [r1]
|
||||
// Move r2 back to account for the last 3 bytes we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r2, r2, #3
|
||||
vext.8 q2, q1, q2, #13
|
||||
b 2f
|
||||
|
||||
1:
|
||||
vld1.8 {q2}, [r2]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost byte
|
||||
// and shift q2 to have 3x the first byte at the front.
|
||||
vdup.8 q3, d4[0]
|
||||
// Move r2 back to account for the last 3 bytes we loaded before,
|
||||
// which we shifted out.
|
||||
sub r2, r2, #3
|
||||
vext.8 q2, q3, q2, #13
|
||||
|
||||
2:
|
||||
vmovl.u8 q3, d5
|
||||
vmovl.u8 q2, d4
|
||||
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r4, #11
|
||||
bge 4f // If w >= 11, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 11, w+3 pixels valid in q1-q2. For w=9 or w=10,
|
||||
// this ends up called again; it's not strictly needed in those
|
||||
// cases (we pad enough here), but keeping the code as simple as possible.
|
||||
|
||||
// The padding pixel is q1/2.h[w+2]. r2 points at the next input, ie
|
||||
// q1/2.h[16]. Thus read from r2[w-14] to find the padding pixel.
|
||||
sub lr, r4, #14
|
||||
// Insert padding in q1/2.h[w+3] onwards; fuse the +3 (*2) into the
|
||||
// buffer pointer.
|
||||
movrel_local r3, right_ext_mask, -6
|
||||
ldrb lr, [r2, lr]
|
||||
sub r3, r3, r4, lsl #1
|
||||
vdup.16 q13, lr
|
||||
vld1.8 {q10, q11}, [r3]
|
||||
|
||||
vbit q2, q13, q10
|
||||
vbit q3, q13, q11
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 q10, q2, q3, #4
|
||||
vext.8 q11, q2, q3, #8
|
||||
vext.8 q9, q2, q3, #2
|
||||
vext.8 q12, q2, q3, #10
|
||||
vext.8 q13, q2, q3, #12
|
||||
vext.8 q8, q2, q3, #6
|
||||
vadd.i16 q10, q10, q11
|
||||
vadd.i16 q9, q9, q12
|
||||
vadd.i16 q13, q13, q2
|
||||
vld1.16 {q6}, [r7, :128]!
|
||||
vshl.s16 q2, q8, #7
|
||||
vld1.16 {q11}, [r11, :128]!
|
||||
vsub.s16 q2, q2, q14
|
||||
vld1.16 {q7}, [r8, :128]!
|
||||
vmul.s16 q4, q8, d0[3]
|
||||
vmla.s16 q4, q10, d1[0]
|
||||
vmla.s16 q4, q9, d1[1]
|
||||
vmla.s16 q4, q13, d1[2]
|
||||
|
||||
vld1.16 {q10}, [r10, :128]!
|
||||
vqadd.s16 q4, q4, q2
|
||||
|
||||
vld1.16 {q9}, [r9, :128]!
|
||||
vshr.s16 q4, q4, #3
|
||||
vld1.16 {q5}, [r6, :128]!
|
||||
vadd.s16 q4, q4, q15
|
||||
|
||||
vadd.s16 q6, q6, q11
|
||||
vadd.s16 q7, q7, q10
|
||||
vadd.s16 q5, q5, q4
|
||||
|
||||
vmull.s16 q8, d18, d2[3]
|
||||
vmlal.s16 q8, d12, d2[1]
|
||||
vmlal.s16 q8, d14, d2[2]
|
||||
vmlal.s16 q8, d10, d2[0]
|
||||
|
||||
vmull.s16 q9, d19, d2[3]
|
||||
vmlal.s16 q9, d13, d2[1]
|
||||
vmlal.s16 q9, d15, d2[2]
|
||||
vmlal.s16 q9, d11, d2[0]
|
||||
|
||||
vqrshrun.s32 d16, q8, #11
|
||||
vqrshrun.s32 d17, q9, #11
|
||||
vst1.16 {q4}, [r12, :128]!
|
||||
vqmovun.s16 d16, q8
|
||||
subs r4, r4, #8
|
||||
vst1.8 {d16}, [r0, :64]!
|
||||
|
||||
ble 9f
|
||||
vmov q2, q3
|
||||
vld1.8 {d6}, [r2]!
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
vmovl.u8 q3, d6
|
||||
bne 4b // If we don't need to pad, just keep filtering.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
// Reload ptrs from arguments on the stack
|
||||
ldr lr, [sp, #108]
|
||||
// Rotate the window of pointers. Shift the 6 pointers downwards one step.
|
||||
ldrd r6, r7, [lr, #4]
|
||||
ldrd r8, r9, [lr, #12]
|
||||
ldrd r10, r11, [lr, #20]
|
||||
|
||||
strd r6, r7, [lr]
|
||||
strd r8, r9, [lr, #8]
|
||||
strd r10, r11, [lr, #16]
|
||||
// The topmost pointer, ptrs[6], which isn't used as input, is set to
|
||||
// ptrs[0], which will be used as output for the next _hv call.
|
||||
// At the start of the filtering, the caller may set ptrs[6] to the
|
||||
// right next buffer to fill in, instead.
|
||||
str r6, [lr, #24]
|
||||
|
||||
vpop {q4-q7}
|
||||
pop {r4-r11,pc}
|
||||
endfunc
|
||||
|
||||
#include "looprestoration_tmpl.S"
|
||||
|
||||
// void dav1d_sgr_box3_row_h_8bpc_neon(int32_t *sumsq, int16_t *sum,
|
||||
// const pixel (*left)[4],
|
||||
// const pixel *src, const int w,
|
||||
// const enum LrEdgeFlags edges);
|
||||
function sgr_box3_row_h_8bpc_neon, export=1
|
||||
push {r4-r5,lr}
|
||||
ldrd r4, r5, [sp, #12]
|
||||
add r4, r4, #2 // w += 2
|
||||
|
||||
tst r5, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
cmp r2, #0
|
||||
bne 0f
|
||||
|
||||
// LR_HAVE_LEFT && left == NULL
|
||||
sub r3, r3, #2
|
||||
vld1.8 {q0}, [r3]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.8 {q0}, [r3]!
|
||||
vld1.32 {d3[]}, [r2]
|
||||
// Move r3 back to account for the last 2 bytes we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r3, r3, #2
|
||||
vext.8 q0, q1, q0, #14
|
||||
b 2f
|
||||
|
||||
1:
|
||||
vld1.8 {q0}, [r3]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost byte
|
||||
// and shift q0 to have 2x the first byte at the front.
|
||||
vdup.8 q1, d0[0]
|
||||
// Move r3 back to account for the last 2 bytes we loaded before,
|
||||
// which we shifted out.
|
||||
sub r3, r3, #2
|
||||
vext.8 q0, q1, q0, #14
|
||||
|
||||
2:
|
||||
vmull.u8 q1, d0, d0
|
||||
vmull.u8 q2, d1, d1
|
||||
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
// If we'll need to pad the right edge, load that byte to pad with
|
||||
// here since we can find it pretty easily from here.
|
||||
sub lr, r4, #(2 + 16 - 2 + 1)
|
||||
ldrb lr, [r3, lr]
|
||||
// Fill q14 with the right padding pixel
|
||||
vdup.8 q14, lr
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r4, #10
|
||||
bge 4f // If w >= 10, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 10, w pixels valid in q0. For w=9, this ends up called
|
||||
// again; it's not strictly needed in those cases (we pad enough here),
|
||||
// but keeping the code as simple as possible.
|
||||
|
||||
// Insert padding in q0.b[w] onwards
|
||||
movrel_local lr, right_ext_mask
|
||||
sub lr, lr, r4
|
||||
vld1.8 {q13}, [lr]
|
||||
|
||||
vbit q0, q14, q13
|
||||
|
||||
// Update the precalculated squares
|
||||
vmull.u8 q1, d0, d0
|
||||
vmull.u8 q2, d1, d1
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 d16, d0, d1, #1
|
||||
vext.8 d17, d0, d1, #2
|
||||
vaddl.u8 q3, d0, d16
|
||||
vext.8 q9, q1, q2, #2
|
||||
vaddw.u8 q3, q3, d17
|
||||
|
||||
vext.8 q10, q1, q2, #4
|
||||
|
||||
vaddl.u16 q12, d2, d18
|
||||
vaddl.u16 q13, d3, d19
|
||||
vaddw.u16 q12, q12, d20
|
||||
vaddw.u16 q13, q13, d21
|
||||
|
||||
subs r4, r4, #8
|
||||
vst1.16 {q3}, [r1, :128]!
|
||||
vst1.32 {q12, q13}, [r0, :128]!
|
||||
|
||||
ble 9f
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
vld1.8 {d6}, [r3]!
|
||||
vmov q1, q2
|
||||
vext.8 q0, q0, q3, #8
|
||||
vmull.u8 q2, d6, d6
|
||||
|
||||
bne 4b // If we don't need to pad, just keep summing.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
pop {r4-r5,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_box5_row_h_8bpc_neon(int32_t *sumsq, int16_t *sum,
|
||||
// const pixel (*left)[4],
|
||||
// const pixel *src, const int w,
|
||||
// const enum LrEdgeFlags edges);
|
||||
function sgr_box5_row_h_8bpc_neon, export=1
|
||||
push {r4-r5,lr}
|
||||
ldrd r4, r5, [sp, #12]
|
||||
add r4, r4, #2 // w += 2
|
||||
|
||||
tst r5, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
cmp r2, #0
|
||||
bne 0f
|
||||
|
||||
// LR_HAVE_LEFT && left == NULL
|
||||
sub r3, r3, #3
|
||||
vld1.8 {q0}, [r3]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.8 {q0}, [r3]!
|
||||
vld1.32 {d3[]}, [r2]
|
||||
// Move r3 back to account for the last 3 bytes we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r3, r3, #3
|
||||
vext.8 q0, q1, q0, #13
|
||||
b 2f
|
||||
|
||||
1:
|
||||
vld1.8 {q0}, [r3]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost byte
|
||||
// and shift q0 to have 3x the first byte at the front.
|
||||
vdup.8 q1, d0[0]
|
||||
// Move r3 back to account for the last 3 bytes we loaded before,
|
||||
// which we shifted out.
|
||||
sub r3, r3, #3
|
||||
vext.8 q0, q1, q0, #13
|
||||
|
||||
2:
|
||||
vmull.u8 q1, d0, d0
|
||||
vmull.u8 q2, d1, d1
|
||||
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
// If we'll need to pad the right edge, load that byte to pad with
|
||||
// here since we can find it pretty easily from here.
|
||||
sub lr, r4, #(2 + 16 - 3 + 1)
|
||||
ldrb lr, [r3, lr]
|
||||
// Fill q14 with the right padding pixel
|
||||
vdup.8 q14, lr
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r4, #11
|
||||
bge 4f // If w >= 11, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 11, w+1 pixels valid in q0. For w=9 or w=10,
|
||||
// this ends up called again; it's not strictly needed in those
|
||||
// cases (we pad enough here), but keeping the code as simple as possible.
|
||||
|
||||
// Insert padding in q0.b[w+1] onwards; fuse the +1 into the
|
||||
// buffer pointer.
|
||||
movrel_local lr, right_ext_mask, -1
|
||||
sub lr, lr, r4
|
||||
vld1.8 {q13}, [lr]
|
||||
|
||||
vbit q0, q14, q13
|
||||
|
||||
// Update the precalculated squares
|
||||
vmull.u8 q1, d0, d0
|
||||
vmull.u8 q2, d1, d1
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 d16, d0, d1, #1
|
||||
vext.8 d17, d0, d1, #2
|
||||
vext.8 d18, d0, d1, #3
|
||||
vext.8 d19, d0, d1, #4
|
||||
vaddl.u8 q3, d0, d16
|
||||
vaddl.u8 q12, d17, d18
|
||||
vaddw.u8 q3, q3, d19
|
||||
vadd.u16 q3, q3, q12
|
||||
|
||||
vext.8 q8, q1, q2, #2
|
||||
vext.8 q9, q1, q2, #4
|
||||
vext.8 q10, q1, q2, #6
|
||||
vext.8 q11, q1, q2, #8
|
||||
vaddl.u16 q12, d2, d16
|
||||
vaddl.u16 q13, d3, d17
|
||||
vaddl.u16 q8, d18, d20
|
||||
vaddl.u16 q9, d19, d21
|
||||
vaddw.u16 q12, q12, d22
|
||||
vaddw.u16 q13, q13, d23
|
||||
vadd.i32 q12, q12, q8
|
||||
vadd.i32 q13, q13, q9
|
||||
|
||||
subs r4, r4, #8
|
||||
vst1.16 {q3}, [r1, :128]!
|
||||
vst1.32 {q12, q13}, [r0, :128]!
|
||||
|
||||
ble 9f
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
vld1.8 {d6}, [r3]!
|
||||
vmov q1, q2
|
||||
vext.8 q0, q0, q3, #8
|
||||
vmull.u8 q2, d6, d6
|
||||
bne 4b // If we don't need to pad, just keep summing.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
pop {r4-r5,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_box35_row_h_8bpc_neon(int32_t *sumsq3, int16_t *sum3,
|
||||
// int32_t *sumsq5, int16_t *sum5,
|
||||
// const pixel (*left)[4],
|
||||
// const pixel *src, const int w,
|
||||
// const enum LrEdgeFlags edges);
|
||||
function sgr_box35_row_h_8bpc_neon, export=1
|
||||
push {r4-r7,lr}
|
||||
ldrd r4, r5, [sp, #20]
|
||||
ldrd r6, r7, [sp, #28]
|
||||
add r6, r6, #2 // w += 2
|
||||
|
||||
tst r7, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
cmp r4, #0
|
||||
bne 0f
|
||||
|
||||
// LR_HAVE_LEFT && left == NULL
|
||||
sub r5, r5, #3
|
||||
vld1.8 {q0}, [r5]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.8 {q0}, [r5]!
|
||||
vld1.32 {d3[]}, [r4]
|
||||
// Move r3 back to account for the last 3 bytes we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r5, r5, #3
|
||||
vext.8 q0, q1, q0, #13
|
||||
b 2f
|
||||
|
||||
1:
|
||||
vld1.8 {q0}, [r5]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost byte
|
||||
// and shift q0 to have 3x the first byte at the front.
|
||||
vdup.8 q1, d0[0]
|
||||
// Move r3 back to account for the last 3 bytes we loaded before,
|
||||
// which we shifted out.
|
||||
sub r5, r5, #3
|
||||
vext.8 q0, q1, q0, #13
|
||||
|
||||
2:
|
||||
vmull.u8 q1, d0, d0
|
||||
vmull.u8 q2, d1, d1
|
||||
|
||||
tst r7, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
// If we'll need to pad the right edge, load that byte to pad with
|
||||
// here since we can find it pretty easily from here.
|
||||
sub lr, r6, #(2 + 16 - 3 + 1)
|
||||
ldrb lr, [r5, lr]
|
||||
// Fill q14 with the right padding pixel
|
||||
vdup.8 q14, lr
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r6, #11
|
||||
bge 4f // If w >= 11, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 11, w+1 pixels valid in q0. For w=9 or w=10,
|
||||
// this ends up called again; it's not strictly needed in those
|
||||
// cases (we pad enough here), but keeping the code as simple as possible.
|
||||
|
||||
// Insert padding in q0.b[w+1] onwards; fuse the +1 into the
|
||||
// buffer pointer.
|
||||
movrel_local lr, right_ext_mask, -1
|
||||
sub lr, lr, r6
|
||||
vld1.8 {q13}, [lr]
|
||||
|
||||
vbit q0, q14, q13
|
||||
|
||||
// Update the precalculated squares
|
||||
vmull.u8 q1, d0, d0
|
||||
vmull.u8 q2, d1, d1
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 d16, d0, d1, #1
|
||||
vext.8 d17, d0, d1, #2
|
||||
vext.8 d18, d0, d1, #3
|
||||
vext.8 d19, d0, d1, #4
|
||||
vaddl.u8 q3, d16, d17
|
||||
vaddl.u8 q12, d0, d19
|
||||
vaddw.u8 q3, q3, d18
|
||||
|
||||
vext.8 q8, q1, q2, #2
|
||||
vext.8 q9, q1, q2, #4
|
||||
vext.8 q10, q1, q2, #6
|
||||
vext.8 q11, q1, q2, #8
|
||||
|
||||
vst1.16 {q3}, [r1, :128]!
|
||||
vadd.u16 q3, q3, q12
|
||||
|
||||
vaddl.u16 q12, d16, d18
|
||||
vaddl.u16 q13, d17, d19
|
||||
vaddl.u16 q8, d2, d22
|
||||
vaddl.u16 q9, d3, d23
|
||||
vaddw.u16 q12, q12, d20
|
||||
vaddw.u16 q13, q13, d21
|
||||
|
||||
vst1.32 {q12, q13}, [r0, :128]!
|
||||
vadd.i32 q12, q12, q8
|
||||
vadd.i32 q13, q13, q9
|
||||
|
||||
subs r6, r6, #8
|
||||
vst1.16 {q3}, [r3, :128]!
|
||||
vst1.32 {q12, q13}, [r2, :128]!
|
||||
|
||||
ble 9f
|
||||
tst r7, #2 // LR_HAVE_RIGHT
|
||||
vld1.8 {d6}, [r5]!
|
||||
vmov q1, q2
|
||||
vext.8 q0, q0, q3, #8
|
||||
vmull.u8 q2, d6, d6
|
||||
bne 4b // If we don't need to pad, just keep summing.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
pop {r4-r7,pc}
|
||||
endfunc
|
||||
|
||||
sgr_funcs 8
|
||||
757
media/libdav1d/src/src/arm/32/looprestoration16.S
Normal file
757
media/libdav1d/src/src/arm/32/looprestoration16.S
Normal file
|
|
@ -0,0 +1,757 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2020, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
const right_ext_mask_buf
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
right_ext_mask:
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
endconst
|
||||
|
||||
// void dav1d_wiener_filter_h_16bpc_neon(int16_t *dst, const pixel (*left)[4],
|
||||
// const pixel *src, const int16_t fh[8],
|
||||
// const int w,
|
||||
// enum LrEdgeFlags edges,
|
||||
// const int bitdepth_max);
|
||||
function wiener_filter_h_16bpc_neon, export=1
|
||||
push {r4-r6,lr}
|
||||
ldrd r4, r5, [sp, #16]
|
||||
ldr r6, [sp, #24] // bitdepth_max
|
||||
vld1.16 {q0}, [r3, :128]
|
||||
clz r6, r6
|
||||
vmov.i32 q14, #1
|
||||
sub r12, r6, #38 // -(bitdepth + 6)
|
||||
sub r6, r6, #25 // -round_bits_h
|
||||
neg r12, r12 // bitdepth + 6
|
||||
vdup.32 q1, r12
|
||||
vdup.32 q13, r6 // -round_bits_h
|
||||
vmov.i16 q15, #8192
|
||||
vshl.u32 q14, q14, q1 // 1 << (bitdepth + 6)
|
||||
vmvn.i16 q12, #0x8000 // 0x7fff = (1 << 15) - 1
|
||||
|
||||
// Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL
|
||||
tst r5, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
// LR_HAVE_LEFT
|
||||
cmp r1, #0
|
||||
bne 0f
|
||||
// left == NULL
|
||||
sub r2, r2, #6
|
||||
vld1.16 {q2, q3}, [r2]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.16 {q2, q3}, [r2]!
|
||||
vld1.16 {d3}, [r1]!
|
||||
// Move r2 back to account for the last 3 pixels we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r2, r2, #6
|
||||
vext.8 q3, q2, q3, #10
|
||||
vext.8 q2, q1, q2, #10
|
||||
b 2f
|
||||
1:
|
||||
vld1.16 {q2, q3}, [r2]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost pixel
|
||||
// and shift q2/q3 to have 3x the first pixel at the front.
|
||||
vdup.16 q1, d4[0]
|
||||
// Move r2 back to account for the last 3 pixels we loaded before,
|
||||
// which we shifted out.
|
||||
sub r2, r2, #6
|
||||
vext.8 q3, q2, q3, #10
|
||||
vext.8 q2, q1, q2, #10
|
||||
|
||||
2:
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r4, #11
|
||||
bge 4f // If w >= 11, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 11, w+3 pixels valid in q2-q3. For w=9 or w=10,
|
||||
// this ends up called again; it's not strictly needed in those
|
||||
// cases (we pad enough here), but keeping the code as simple as possible.
|
||||
|
||||
// The padding pixel is q1/2.h[w+2]. r2 points at the next input, ie
|
||||
// q1/2.h[16]. Thus read from r2[w-14] to find the padding pixel.
|
||||
sub r12, r4, #14
|
||||
lsl r12, r12, #1
|
||||
// Insert padding in q2/3.h[w+3] onwards; fuse the +3 (*2) into the
|
||||
// buffer pointer.
|
||||
movrel_local r3, right_ext_mask, -6
|
||||
ldrh r12, [r2, r12]
|
||||
sub r3, r3, r4, lsl #1
|
||||
vdup.16 q11, r12
|
||||
vld1.8 {q9, q10}, [r3]
|
||||
|
||||
vbit q2, q11, q9
|
||||
vbit q3, q11, q10
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 q9, q2, q3, #4
|
||||
vext.8 q10, q2, q3, #8
|
||||
vext.8 q8, q2, q3, #2
|
||||
vext.8 q11, q2, q3, #10
|
||||
vadd.i16 q10, q10, q9
|
||||
vadd.i16 q11, q11, q8
|
||||
vext.8 q8, q2, q3, #12
|
||||
vext.8 q9, q2, q3, #6
|
||||
vadd.i16 q2, q2, q8
|
||||
vmull.s16 q8, d18, d0[3]
|
||||
vmlal.s16 q8, d20, d1[0]
|
||||
vmlal.s16 q8, d22, d1[1]
|
||||
vmlal.s16 q8, d4, d1[2]
|
||||
vmull.s16 q9, d19, d0[3]
|
||||
vmlal.s16 q9, d21, d1[0]
|
||||
vmlal.s16 q9, d23, d1[1]
|
||||
vmlal.s16 q9, d5, d1[2]
|
||||
|
||||
vadd.i32 q8, q8, q14
|
||||
vadd.i32 q9, q9, q14
|
||||
vrshl.s32 q8, q8, q13
|
||||
vrshl.s32 q9, q9, q13
|
||||
vqmovun.s32 d16, q8
|
||||
vqmovun.s32 d17, q9
|
||||
vmin.u16 q8, q8, q12
|
||||
vsub.i16 q8, q8, q15
|
||||
subs r4, r4, #8
|
||||
vst1.16 {q8}, [r0, :128]!
|
||||
|
||||
ble 9f
|
||||
vmov q2, q3
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
vld1.16 {q3}, [r2]!
|
||||
bne 4b // If we don't need to pad, just keep filtering.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
pop {r4-r6,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_wiener_filter_v_16bpc_neon(pixel *dst, int16_t **ptrs,
|
||||
// const int16_t fv[8], const int w,
|
||||
// const int bitdepth_max);
|
||||
function wiener_filter_v_16bpc_neon, export=1
|
||||
push {r4-r9,lr}
|
||||
vpush {q4-q7}
|
||||
|
||||
ldr lr, [sp, #92] // bitdepth_max
|
||||
vld1.16 {q0}, [r2, :128]
|
||||
vdup.16 q2, lr
|
||||
clz lr, lr
|
||||
sub lr, lr, #11 // round_bits_v
|
||||
|
||||
vdup.32 q1, lr
|
||||
|
||||
ldrd r4, r5, [r1]
|
||||
ldrd r6, r7, [r1, #8]
|
||||
ldrd r8, r9, [r1, #16]
|
||||
|
||||
vneg.s32 q1, q1 // -round_bits_v
|
||||
|
||||
1:
|
||||
vld1.16 {q4, q5}, [r4, :128]!
|
||||
vld1.16 {q6, q7}, [r5, :128]!
|
||||
vld1.16 {q8, q9}, [r6, :128]!
|
||||
vld1.16 {q10, q11}, [r7, :128]!
|
||||
vld1.16 {q12, q13}, [r8, :128]!
|
||||
vld1.16 {q14, q15}, [r9, :128]!
|
||||
|
||||
subs r3, r3, #16
|
||||
|
||||
vmull.s16 q3, d8, d0[0]
|
||||
vmlal.s16 q3, d12, d0[1]
|
||||
vmlal.s16 q3, d16, d0[2]
|
||||
vmlal.s16 q3, d20, d0[3]
|
||||
vmlal.s16 q3, d24, d1[0]
|
||||
vmlal.s16 q3, d28, d1[1]
|
||||
vmlal.s16 q3, d28, d1[2]
|
||||
vmull.s16 q4, d9, d0[0]
|
||||
vmlal.s16 q4, d13, d0[1]
|
||||
vmlal.s16 q4, d17, d0[2]
|
||||
vmlal.s16 q4, d21, d0[3]
|
||||
vmlal.s16 q4, d25, d1[0]
|
||||
vmlal.s16 q4, d29, d1[1]
|
||||
vmlal.s16 q4, d29, d1[2]
|
||||
|
||||
vmull.s16 q6, d10, d0[0]
|
||||
vmlal.s16 q6, d14, d0[1]
|
||||
vmlal.s16 q6, d18, d0[2]
|
||||
vmlal.s16 q6, d22, d0[3]
|
||||
vmlal.s16 q6, d26, d1[0]
|
||||
vmlal.s16 q6, d30, d1[1]
|
||||
vmlal.s16 q6, d30, d1[2]
|
||||
vmull.s16 q5, d11, d0[0]
|
||||
vmlal.s16 q5, d15, d0[1]
|
||||
vmlal.s16 q5, d19, d0[2]
|
||||
vmlal.s16 q5, d23, d0[3]
|
||||
vmlal.s16 q5, d27, d1[0]
|
||||
vmlal.s16 q5, d31, d1[1]
|
||||
vmlal.s16 q5, d31, d1[2]
|
||||
|
||||
vrshl.s32 q3, q3, q1 // round_bits_v
|
||||
vrshl.s32 q4, q4, q1
|
||||
vrshl.s32 q6, q6, q1
|
||||
vrshl.s32 q5, q5, q1
|
||||
vqmovun.s32 d6, q3
|
||||
vqmovun.s32 d7, q4
|
||||
vqmovun.s32 d8, q6
|
||||
vqmovun.s32 d9, q5
|
||||
vmin.u16 q3, q3, q2 // bitdepth_max
|
||||
vmin.u16 q4, q4, q2
|
||||
vst1.16 {q3, q4}, [r0, :128]!
|
||||
bgt 1b
|
||||
|
||||
// Shift the pointers, but only update the first 5; the 6th pointer is
|
||||
// kept as it was before (and the 7th is implicitly identical to the
|
||||
// 6th).
|
||||
ldrd r4, r5, [r1, #4]
|
||||
ldrd r6, r7, [r1, #12]
|
||||
ldr r8, [r1, #20]
|
||||
strd r4, r5, [r1]
|
||||
strd r6, r7, [r1, #8]
|
||||
str r8, [r1, #16]
|
||||
|
||||
vpop {q4-q7}
|
||||
pop {r4-r9,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_wiener_filter_hv_16bpc_neon(pixel *dst, const pixel (*left)[4],
|
||||
// const pixel *src,
|
||||
// const int16_t filter[2][8],
|
||||
// const int w,
|
||||
// const enum LrEdgeFlags edges,
|
||||
// int16_t **ptrs,
|
||||
// const int bitdepth_max);
|
||||
function wiener_filter_hv_16bpc_neon, export=1
|
||||
push {r4-r11,lr}
|
||||
vpush {q4-q7}
|
||||
ldrd r4, r5, [sp, #100]
|
||||
ldrd r6, r7, [sp, #108]
|
||||
vld1.16 {q0, q1}, [r3, :128]
|
||||
vdup.16 q11, r7 // bitdepth_max
|
||||
clz r7, r7
|
||||
vmov.i32 q14, #1
|
||||
sub r12, r7, #38 // -(bitdepth + 6)
|
||||
sub lr, r7, #11 // round_bits_v
|
||||
sub r7, r7, #25 // -round_bits_h
|
||||
neg r12, r12 // bitdepth + 6
|
||||
vdup.32 q2, r12
|
||||
vdup.32 q13, r7 // -round_bits_h
|
||||
vdup.32 q10, lr // round_bits_v
|
||||
mov lr, r6
|
||||
vmov.i16 q15, #8192
|
||||
vshl.u32 q14, q14, q2 // 1 << (bitdepth + 6)
|
||||
vneg.s32 q10, q10 // -round_bits_v
|
||||
|
||||
ldrd r6, r7, [lr]
|
||||
ldrd r8, r9, [lr, #8]
|
||||
ldrd r10, r11, [lr, #16]
|
||||
ldr r12, [lr, #24]
|
||||
|
||||
// Set up the src pointers to include the left edge, for LR_HAVE_LEFT, left == NULL
|
||||
tst r5, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
// LR_HAVE_LEFT
|
||||
cmp r1, #0
|
||||
bne 0f
|
||||
// left == NULL
|
||||
sub r2, r2, #6
|
||||
vld1.16 {q2, q3}, [r2]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.16 {q2, q3}, [r2]!
|
||||
vld1.16 {d9}, [r1]!
|
||||
// Move r2 back to account for the last 3 pixels we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r2, r2, #6
|
||||
vext.8 q3, q2, q3, #10
|
||||
vext.8 q2, q4, q2, #10
|
||||
b 2f
|
||||
1:
|
||||
vld1.16 {q2, q3}, [r2]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost pixel
|
||||
// and shift q2/q3 to have 3x the first pixel at the front.
|
||||
vdup.16 q4, d4[0]
|
||||
// Move r2 back to account for the last 3 pixels we loaded before,
|
||||
// which we shifted out.
|
||||
sub r2, r2, #6
|
||||
vext.8 q3, q2, q3, #10
|
||||
vext.8 q2, q4, q2, #10
|
||||
|
||||
2:
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r4, #11
|
||||
bge 4f // If w >= 11, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 11, w+3 pixels valid in q2-q3. For w=9 or w=10,
|
||||
// this ends up called again; it's not strictly needed in those
|
||||
// cases (we pad enough here), but keeping the code as simple as possible.
|
||||
|
||||
// The padding pixel is q1/2.h[w+2]. r2 points at the next input, ie
|
||||
// q1/2.h[16]. Thus read from r2[w-14] to find the padding pixel.
|
||||
sub lr, r4, #14
|
||||
lsl lr, lr, #1
|
||||
// Insert padding in q2/3.h[w+3] onwards; fuse the +3 (*2) into the
|
||||
// buffer pointer.
|
||||
movrel_local r3, right_ext_mask, -6
|
||||
ldrh lr, [r2, lr]
|
||||
sub r3, r3, r4, lsl #1
|
||||
vdup.16 q4, lr
|
||||
vld1.8 {q8, q9}, [r3]
|
||||
|
||||
vbit q2, q4, q8
|
||||
vbit q3, q4, q9
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 q5, q2, q3, #4
|
||||
vext.8 q6, q2, q3, #8
|
||||
vext.8 q4, q2, q3, #2
|
||||
vext.8 q7, q2, q3, #10
|
||||
vadd.i16 q6, q6, q5
|
||||
vadd.i16 q7, q7, q4
|
||||
vext.8 q4, q2, q3, #12
|
||||
vext.8 q5, q2, q3, #6
|
||||
vadd.i16 q2, q2, q4
|
||||
vld1.16 {q4}, [r6, :128]!
|
||||
vmull.s16 q8, d10, d0[3]
|
||||
vmlal.s16 q8, d12, d1[0]
|
||||
vmlal.s16 q8, d14, d1[1]
|
||||
vmlal.s16 q8, d4, d1[2]
|
||||
vmull.s16 q9, d11, d0[3]
|
||||
vmlal.s16 q9, d13, d1[0]
|
||||
vmlal.s16 q9, d15, d1[1]
|
||||
vmlal.s16 q9, d5, d1[2]
|
||||
vld1.16 {q5}, [r7, :128]!
|
||||
|
||||
vmvn.i16 q12, #0x8000 // 0x7fff = (1 << 15) - 1
|
||||
|
||||
vadd.i32 q8, q8, q14
|
||||
vadd.i32 q9, q9, q14
|
||||
vld1.16 {q6}, [r8, :128]!
|
||||
vrshl.s32 q8, q8, q13
|
||||
vrshl.s32 q9, q9, q13
|
||||
vqmovun.s32 d16, q8
|
||||
vqmovun.s32 d17, q9
|
||||
vld1.16 {q7}, [r9, :128]!
|
||||
vmin.u16 q8, q8, q12
|
||||
vld1.16 {q9}, [r10, :128]!
|
||||
vsub.i16 q8, q8, q15
|
||||
|
||||
vld1.16 {q2}, [r11, :128]!
|
||||
|
||||
vmull.s16 q12, d8, d2[0]
|
||||
vmlal.s16 q12, d10, d2[1]
|
||||
vmlal.s16 q12, d12, d2[2]
|
||||
vmlal.s16 q12, d14, d2[3]
|
||||
vmlal.s16 q12, d18, d3[0]
|
||||
vmlal.s16 q12, d4, d3[1]
|
||||
vmlal.s16 q12, d16, d3[2]
|
||||
vmull.s16 q4, d9, d2[0]
|
||||
vmlal.s16 q4, d11, d2[1]
|
||||
vmlal.s16 q4, d13, d2[2]
|
||||
vmlal.s16 q4, d15, d2[3]
|
||||
vmlal.s16 q4, d19, d3[0]
|
||||
vmlal.s16 q4, d5, d3[1]
|
||||
vmlal.s16 q4, d17, d3[2]
|
||||
|
||||
vrshl.s32 q12, q12, q10 // round_bits_v
|
||||
vrshl.s32 q4, q4, q10
|
||||
vqmovun.s32 d24, q12
|
||||
vqmovun.s32 d25, q4
|
||||
vst1.16 {q8}, [r12, :128]!
|
||||
vmin.u16 q12, q12, q11 // bitdepth_max
|
||||
subs r4, r4, #8
|
||||
vst1.16 {q12}, [r0, :128]!
|
||||
|
||||
ble 9f
|
||||
vmov q2, q3
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
vld1.16 {q3}, [r2]!
|
||||
bne 4b // If we don't need to pad, just keep filtering.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
// Reload ptrs from arguments on the stack
|
||||
ldr lr, [sp, #108]
|
||||
// Rotate the window of pointers. Shift the 6 pointers downwards one step.
|
||||
ldrd r6, r7, [lr, #4]
|
||||
ldrd r8, r9, [lr, #12]
|
||||
ldrd r10, r11, [lr, #20]
|
||||
|
||||
strd r6, r7, [lr]
|
||||
strd r8, r9, [lr, #8]
|
||||
strd r10, r11, [lr, #16]
|
||||
// The topmost pointer, ptrs[6], which isn't used as input, is set to
|
||||
// ptrs[0], which will be used as output for the next _hv call.
|
||||
// At the start of the filtering, the caller may set ptrs[6] to the
|
||||
// right next buffer to fill in, instead.
|
||||
str r6, [lr, #24]
|
||||
|
||||
vpop {q4-q7}
|
||||
pop {r4-r11,pc}
|
||||
endfunc
|
||||
|
||||
#include "looprestoration_tmpl.S"
|
||||
|
||||
// void dav1d_sgr_box3_row_h_16bpc_neon(int32_t *sumsq, int16_t *sum,
|
||||
// const pixel (*left)[4],
|
||||
// const pixel *src, const int w,
|
||||
// const enum LrEdgeFlags edges);
|
||||
function sgr_box3_row_h_16bpc_neon, export=1
|
||||
push {r4-r5,lr}
|
||||
ldrd r4, r5, [sp, #12]
|
||||
add r4, r4, #2 // w += 2
|
||||
|
||||
tst r5, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
cmp r2, #0
|
||||
bne 0f
|
||||
|
||||
// LR_HAVE_LEFT && left == NULL
|
||||
sub r3, r3, #4
|
||||
vld1.8 {q0, q1}, [r3]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.8 {q0, q1}, [r3]!
|
||||
vld1.16 {d5}, [r2]
|
||||
// Move r3 back to account for the last 2 pixels we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r3, r3, #4
|
||||
vext.8 q1, q0, q1, #12
|
||||
vext.8 q0, q2, q0, #12
|
||||
b 2f
|
||||
|
||||
1:
|
||||
vld1.8 {q0, q1}, [r3]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost pixel
|
||||
// and shift q0/q1 to have 2x the first pixel at the front.
|
||||
vdup.16 q2, d0[0]
|
||||
// Move r3 back to account for the last 2 pixels we loaded before,
|
||||
// which we shifted out.
|
||||
sub r3, r3, #4
|
||||
vext.8 q1, q0, q1, #12
|
||||
vext.8 q0, q2, q0, #12
|
||||
|
||||
2:
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
// If we'll need to pad the right edge, load that pixel to pad with
|
||||
// here since we can find it pretty easily from here.
|
||||
sub lr, r4, #(2 + 16 - 2 + 1)
|
||||
lsl lr, lr, #1
|
||||
ldrh lr, [r3, lr]
|
||||
// Fill q14 with the right padding pixel
|
||||
vdup.16 q14, lr
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r4, #10
|
||||
bge 4f // If w >= 10, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 10, w pixels valid in q0-q1. For w=9, this ends up called
|
||||
// again; it's not strictly needed in those cases (we pad enough here),
|
||||
// but keeping the code as simple as possible.
|
||||
|
||||
// Insert padding in q0.h[w] onwards
|
||||
movrel_local lr, right_ext_mask
|
||||
sub lr, lr, r4, lsl #1
|
||||
vld1.8 {q12, q13}, [lr]
|
||||
|
||||
vbit q0, q14, q12
|
||||
vbit q1, q14, q13
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 q8, q0, q1, #2
|
||||
vext.8 q9, q0, q1, #4
|
||||
|
||||
vadd.i16 q2, q0, q8
|
||||
vmull.u16 q12, d0, d0
|
||||
vmlal.u16 q12, d16, d16
|
||||
vmlal.u16 q12, d18, d18
|
||||
vadd.i16 q2, q2, q9
|
||||
vmull.u16 q13, d1, d1
|
||||
vmlal.u16 q13, d17, d17
|
||||
vmlal.u16 q13, d19, d19
|
||||
subs r4, r4, #8
|
||||
vst1.16 {q2}, [r1, :128]!
|
||||
vst1.32 {q12, q13}, [r0, :128]!
|
||||
|
||||
ble 9f
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
vmov q0, q1
|
||||
vld1.16 {q1}, [r3]!
|
||||
|
||||
bne 4b // If we don't need to pad, just keep summing.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
pop {r4-r5,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_box5_row_h_16bpc_neon(int32_t *sumsq, int16_t *sum,
|
||||
// const pixel (*left)[4],
|
||||
// const pixel *src, const int w,
|
||||
// const enum LrEdgeFlags edges);
|
||||
function sgr_box5_row_h_16bpc_neon, export=1
|
||||
push {r4-r5,lr}
|
||||
ldrd r4, r5, [sp, #12]
|
||||
add r4, r4, #2 // w += 2
|
||||
|
||||
tst r5, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
cmp r2, #0
|
||||
bne 0f
|
||||
|
||||
// LR_HAVE_LEFT && left == NULL
|
||||
sub r3, r3, #6
|
||||
vld1.8 {q0, q1}, [r3]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.8 {q0, q1}, [r3]!
|
||||
vld1.16 {d5}, [r2]
|
||||
// Move r3 back to account for the last 2 pixels we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r3, r3, #6
|
||||
vext.8 q1, q0, q1, #10
|
||||
vext.8 q0, q2, q0, #10
|
||||
b 2f
|
||||
|
||||
1:
|
||||
vld1.8 {q0, q1}, [r3]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost pixel
|
||||
// and shift q0/q1 to have 3x the first pixel at the front.
|
||||
vdup.16 q2, d0[0]
|
||||
// Move r3 back to account for the last 3 pixels we loaded before,
|
||||
// which we shifted out.
|
||||
sub r3, r3, #6
|
||||
vext.8 q1, q0, q1, #10
|
||||
vext.8 q0, q2, q0, #10
|
||||
|
||||
2:
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
// If we'll need to pad the right edge, load that pixel to pad with
|
||||
// here since we can find it pretty easily from here.
|
||||
sub lr, r4, #(2 + 16 - 3 + 1)
|
||||
lsl lr, lr, #1
|
||||
ldrh lr, [r3, lr]
|
||||
// Fill q14 with the right padding pixel
|
||||
vdup.16 q14, lr
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r4, #11
|
||||
bge 4f // If w >= 11, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 11, w+1 pixels valid in q0-q1. For w=9 or w=10,
|
||||
// this ends up called again; it's not strictly needed in those
|
||||
// cases (we pad enough here), but keeping the code as simple as possible.
|
||||
|
||||
// Insert padding in q0.h[w+1] onwards; fuse the +1 into the
|
||||
// buffer pointer.
|
||||
movrel_local lr, right_ext_mask, -2
|
||||
sub lr, lr, r4, lsl #1
|
||||
vld1.8 {q12, q13}, [lr]
|
||||
|
||||
vbit q0, q14, q12
|
||||
vbit q1, q14, q13
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 q8, q0, q1, #2
|
||||
vext.8 q9, q0, q1, #4
|
||||
|
||||
vadd.i16 q2, q0, q8
|
||||
vmull.u16 q12, d0, d0
|
||||
vmlal.u16 q12, d16, d16
|
||||
vmlal.u16 q12, d18, d18
|
||||
vadd.i16 q2, q2, q9
|
||||
vmull.u16 q13, d1, d1
|
||||
vmlal.u16 q13, d17, d17
|
||||
vmlal.u16 q13, d19, d19
|
||||
|
||||
vext.8 q8, q0, q1, #6
|
||||
vext.8 q9, q0, q1, #8
|
||||
|
||||
vadd.i16 q2, q2, q8
|
||||
vmlal.u16 q12, d16, d16
|
||||
vmlal.u16 q12, d1, d1
|
||||
vadd.i16 q2, q2, q9
|
||||
vmlal.u16 q13, d17, d17
|
||||
vmlal.u16 q13, d19, d19
|
||||
|
||||
subs r4, r4, #8
|
||||
vst1.16 {q2}, [r1, :128]!
|
||||
vst1.32 {q12, q13}, [r0, :128]!
|
||||
|
||||
ble 9f
|
||||
tst r5, #2 // LR_HAVE_RIGHT
|
||||
vmov q0, q1
|
||||
vld1.16 {q1}, [r3]!
|
||||
bne 4b // If we don't need to pad, just keep summing.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
pop {r4-r5,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_box35_row_h_16bpc_neon(int32_t *sumsq3, int16_t *sum3,
|
||||
// int32_t *sumsq5, int16_t *sum5,
|
||||
// const pixel (*left)[4],
|
||||
// const pixel *src, const int w,
|
||||
// const enum LrEdgeFlags edges);
|
||||
function sgr_box35_row_h_16bpc_neon, export=1
|
||||
push {r4-r7,lr}
|
||||
ldrd r4, r5, [sp, #20]
|
||||
ldrd r6, r7, [sp, #28]
|
||||
add r6, r6, #2 // w += 2
|
||||
|
||||
tst r7, #1 // LR_HAVE_LEFT
|
||||
beq 1f
|
||||
cmp r4, #0
|
||||
bne 0f
|
||||
|
||||
// LR_HAVE_LEFT && left == NULL
|
||||
sub r5, r5, #6
|
||||
vld1.8 {q0, q1}, [r5]!
|
||||
b 2f
|
||||
|
||||
0:
|
||||
// LR_HAVE_LEFT, left != NULL
|
||||
vld1.8 {q0, q1}, [r5]!
|
||||
vld1.16 {d5}, [r4]
|
||||
// Move r3 back to account for the last 2 pixels we loaded earlier,
|
||||
// which we'll shift out.
|
||||
sub r5, r5, #6
|
||||
vext.8 q1, q0, q1, #10
|
||||
vext.8 q0, q2, q0, #10
|
||||
b 2f
|
||||
|
||||
1:
|
||||
vld1.8 {q0, q1}, [r5]!
|
||||
// !LR_HAVE_LEFT, fill q1 with the leftmost pixel
|
||||
// and shift q0/q1 to have 3x the first pixel at the front.
|
||||
vdup.16 q2, d0[0]
|
||||
// Move r3 back to account for the last 3 pixels we loaded before,
|
||||
// which we shifted out.
|
||||
sub r5, r5, #6
|
||||
vext.8 q1, q0, q1, #10
|
||||
vext.8 q0, q2, q0, #10
|
||||
|
||||
2:
|
||||
tst r7, #2 // LR_HAVE_RIGHT
|
||||
bne 4f
|
||||
// If we'll need to pad the right edge, load that pixel to pad with
|
||||
// here since we can find it pretty easily from here.
|
||||
sub lr, r6, #(2 + 16 - 3 + 1)
|
||||
lsl lr, lr, #1
|
||||
ldrh lr, [r5, lr]
|
||||
// Fill q14 with the right padding pixel
|
||||
vdup.16 q14, lr
|
||||
3: // !LR_HAVE_RIGHT
|
||||
|
||||
// Check whether we need to pad the right edge
|
||||
cmp r6, #11
|
||||
bge 4f // If w >= 11, all used input pixels are valid
|
||||
|
||||
// 1 <= w < 11, w+1 pixels valid in q0-q1. For w=9 or w=10,
|
||||
// this ends up called again; it's not strictly needed in those
|
||||
// cases (we pad enough here), but keeping the code as simple as possible.
|
||||
|
||||
// Insert padding in q0.h[w+1] onwards; fuse the +1 into the
|
||||
// buffer pointer.
|
||||
movrel_local lr, right_ext_mask, -2
|
||||
sub lr, lr, r6, lsl #1
|
||||
vld1.8 {q12, q13}, [lr]
|
||||
|
||||
vbit q0, q14, q12
|
||||
vbit q1, q14, q13
|
||||
|
||||
4: // Loop horizontally
|
||||
vext.8 q8, q0, q1, #2
|
||||
vext.8 q9, q0, q1, #4
|
||||
vext.8 q10, q0, q1, #6
|
||||
vext.8 q11, q0, q1, #8
|
||||
|
||||
vadd.i16 q2, q8, q9
|
||||
vadd.i16 q3, q0, q11
|
||||
vadd.i16 q2, q2, q10
|
||||
|
||||
vmull.u16 q12, d16, d16
|
||||
vmlal.u16 q12, d18, d18
|
||||
vmlal.u16 q12, d20, d20
|
||||
vmull.u16 q13, d17, d17
|
||||
vmlal.u16 q13, d19, d19
|
||||
vmlal.u16 q13, d21, d21
|
||||
|
||||
vadd.i16 q3, q3, q2
|
||||
vst1.16 {q2}, [r1, :128]!
|
||||
vst1.32 {q12, q13}, [r0, :128]!
|
||||
|
||||
vmlal.u16 q12, d0, d0
|
||||
vmlal.u16 q12, d22, d22
|
||||
vmlal.u16 q13, d1, d1
|
||||
vmlal.u16 q13, d23, d23
|
||||
|
||||
subs r6, r6, #8
|
||||
vst1.16 {q3}, [r3, :128]!
|
||||
vst1.32 {q12, q13}, [r2, :128]!
|
||||
|
||||
ble 9f
|
||||
tst r7, #2 // LR_HAVE_RIGHT
|
||||
vmov q0, q1
|
||||
vld1.16 {q1}, [r5]!
|
||||
bne 4b // If we don't need to pad, just keep summing.
|
||||
b 3b // If we need to pad, check how many pixels we have left.
|
||||
|
||||
9:
|
||||
pop {r4-r7,pc}
|
||||
endfunc
|
||||
|
||||
sgr_funcs 16
|
||||
216
media/libdav1d/src/src/arm/32/looprestoration_common.S
Normal file
216
media/libdav1d/src/src/arm/32/looprestoration_common.S
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2019, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
// void dav1d_sgr_box3_row_v_neon(int32_t **sumsq, int16_t **sum,
|
||||
// int32_t *sumsq_out, int16_t *sum_out,
|
||||
// const int w);
|
||||
function sgr_box3_row_v_neon, export=1
|
||||
push {r4-r9,lr}
|
||||
ldr r4, [sp, #28]
|
||||
ldrd r6, r7, [r0]
|
||||
ldr r0, [r0, #8]
|
||||
add r4, r4, #2
|
||||
ldrd r8, r9, [r1]
|
||||
ldr r1, [r1, #8]
|
||||
|
||||
1:
|
||||
vld1.32 {q8, q9}, [r6]!
|
||||
vld1.32 {q10, q11}, [r7]!
|
||||
vld1.16 {q14}, [r8]!
|
||||
vld1.16 {q15}, [r9]!
|
||||
subs r4, r4, #8
|
||||
|
||||
vadd.i32 q8, q8, q10
|
||||
vadd.i32 q9, q9, q11
|
||||
|
||||
vld1.32 {q12, q13}, [r0]!
|
||||
|
||||
vadd.i16 q14, q14, q15
|
||||
|
||||
vld1.16 {q15}, [r1]!
|
||||
vadd.i32 q8, q8, q12
|
||||
vadd.i32 q9, q9, q13
|
||||
vadd.i16 q14, q14, q15
|
||||
|
||||
vst1.32 {q8, q9}, [r2]!
|
||||
vst1.16 {q14}, [r3]!
|
||||
|
||||
bgt 1b
|
||||
pop {r4-r9,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_box5_row_v_neon(int32_t **sumsq, int16_t **sum,
|
||||
// int32_t *sumsq_out, int16_t *sum_out,
|
||||
// const int w);
|
||||
function sgr_box5_row_v_neon, export=1
|
||||
push {r4-r11,lr}
|
||||
ldr lr, [sp, #36]
|
||||
|
||||
ldrd r4, r5, [r0]
|
||||
ldrd r6, r7, [r0, #8]
|
||||
ldr r0, [r0, #16]
|
||||
add lr, lr, #2
|
||||
ldrd r8, r9, [r1]
|
||||
ldrd r10, r11, [r1, #8]
|
||||
ldr r1, [r1, #16]
|
||||
|
||||
1:
|
||||
vld1.32 {q8, q9}, [r4]!
|
||||
vld1.32 {q10, q11}, [r5]!
|
||||
vld1.32 {q12, q13}, [r6]!
|
||||
vld1.32 {q14, q15}, [r7]!
|
||||
vld1.16 {q0}, [r8]!
|
||||
vld1.16 {q1}, [r9]!
|
||||
vld1.16 {q2}, [r10]!
|
||||
vld1.16 {q3}, [r11]!
|
||||
subs lr, lr, #8
|
||||
|
||||
vadd.i32 q8, q8, q10
|
||||
vadd.i32 q9, q9, q11
|
||||
vadd.i32 q12, q12, q14
|
||||
vadd.i32 q13, q13, q15
|
||||
|
||||
vld1.32 {q14, q15}, [r0]!
|
||||
|
||||
vadd.i16 q0, q0, q1
|
||||
vadd.i16 q2, q2, q3
|
||||
|
||||
vld1.16 {q3}, [r1]!
|
||||
vadd.i32 q8, q8, q12
|
||||
vadd.i32 q9, q9, q13
|
||||
vadd.i16 q0, q0, q2
|
||||
|
||||
vadd.i32 q8, q8, q14
|
||||
vadd.i32 q9, q9, q15
|
||||
vadd.i16 q0, q0, q3
|
||||
|
||||
vst1.32 {q8, q9}, [r2]!
|
||||
vst1.16 {q0}, [r3]!
|
||||
|
||||
bgt 1b
|
||||
pop {r4-r11,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_calc_row_ab1_neon(int32_t *a, int16_t *b,
|
||||
// const int w, const int strength,
|
||||
// const int bitdepth_max);
|
||||
// void dav1d_sgr_calc_row_ab2_neon(int32_t *a, int16_t *b,
|
||||
// const int w, const int strength,
|
||||
// const int bitdepth_max);
|
||||
function sgr_calc_row_ab1_neon, export=1
|
||||
push {r4-r7,lr}
|
||||
vpush {q4-q7}
|
||||
ldr r4, [sp, #84]
|
||||
clz r6, r4
|
||||
vmov.i32 q15, #9 // n
|
||||
movw r5, #455
|
||||
b sgr_calc_ab_neon
|
||||
endfunc
|
||||
|
||||
function sgr_calc_row_ab2_neon, export=1
|
||||
push {r4-r7,lr}
|
||||
vpush {q4-q7}
|
||||
ldr r4, [sp, #84]
|
||||
clz r6, r4
|
||||
vmov.i32 q15, #25 // n
|
||||
mov r5, #164
|
||||
endfunc
|
||||
|
||||
function sgr_calc_ab_neon
|
||||
movrel r12, X(sgr_x_by_x)
|
||||
sub r6, r6, #24 // -bitdepth_min_8
|
||||
vld1.8 {q8, q9}, [r12, :128]!
|
||||
add r7, r6, r6 // -2*bitdepth_min_8
|
||||
vmov.i8 q11, #5
|
||||
vmov.i8 d10, #55 // idx of last 5
|
||||
vld1.8 {q10}, [r12, :128]
|
||||
vmov.i8 d11, #72 // idx of last 4
|
||||
vmov.i8 d12, #101 // idx of last 3
|
||||
vmov.i8 d13, #169 // idx of last 2
|
||||
vmov.i8 d14, #254 // idx of last 1
|
||||
vmov.i8 d15, #32 // elements consumed in first vtbl
|
||||
add r2, r2, #2 // w += 2
|
||||
vdup.32 q12, r3
|
||||
vsub.i8 q8, q8, q11
|
||||
vsub.i8 q9, q9, q11
|
||||
vsub.i8 q10, q10, q11
|
||||
vdup.32 q13, r7 // -2*bitdepth_min_8
|
||||
1:
|
||||
vld1.32 {q0, q1}, [r0, :128] // a
|
||||
vld1.16 {q2}, [r1, :128] // b
|
||||
vdup.16 q14, r6 // -bitdepth_min_8
|
||||
subs r2, r2, #8
|
||||
vrshl.s32 q0, q0, q13
|
||||
vrshl.s32 q1, q1, q13
|
||||
vrshl.s16 q4, q2, q14
|
||||
vmul.i32 q0, q0, q15 // a * n
|
||||
vmul.i32 q1, q1, q15 // a * n
|
||||
vmull.u16 q3, d8, d8 // b * b
|
||||
vmull.u16 q4, d9, d9 // b * b
|
||||
vqsub.u32 q0, q0, q3 // imax(a * n - b * b, 0)
|
||||
vqsub.u32 q1, q1, q4 // imax(a * n - b * b, 0)
|
||||
vmul.i32 q0, q0, q12 // p * s
|
||||
vmul.i32 q1, q1, q12 // p * s
|
||||
vqshrn.u32 d0, q0, #16
|
||||
vqshrn.u32 d1, q1, #16
|
||||
vqrshrn.u16 d0, q0, #4 // imin(z, 255)
|
||||
|
||||
vcgt.u8 d2, d0, d10 // = -1 if sgr_x_by_x[d0] < 5
|
||||
vcgt.u8 d3, d0, d11 // = -1 if sgr_x_by_x[d0] < 4
|
||||
vtbl.8 d1, {q8, q9}, d0
|
||||
vcgt.u8 d6, d0, d12 // = -1 if sgr_x_by_x[d0] < 3
|
||||
vsub.i8 d9, d0, d15 // indices for vtbx
|
||||
vcgt.u8 d7, d0, d13 // = -1 if sgr_x_by_x[d0] < 2
|
||||
vadd.i8 d2, d2, d3
|
||||
vtbx.8 d1, {q10}, d9
|
||||
vcgt.u8 d8, d0, d14 // = -1 if sgr_x_by_x[d0] < 1
|
||||
vadd.i8 d6, d6, d7
|
||||
vadd.i8 d8, d8, d22
|
||||
vadd.i8 d2, d2, d6
|
||||
vadd.i8 d1, d1, d8
|
||||
vadd.i8 d1, d1, d2
|
||||
vmovl.u8 q0, d1 // x
|
||||
|
||||
vdup.32 q14, r5 // one_by_x
|
||||
|
||||
vmull.u16 q1, d0, d4 // x * BB[i]
|
||||
vmull.u16 q2, d1, d5 // x * BB[i]
|
||||
vmul.i32 q1, q1, q14 // x * BB[i] * sgr_one_by_x
|
||||
vmul.i32 q2, q2, q14 // x * BB[i] * sgr_one_by_x
|
||||
vrshr.s32 q1, q1, #12 // AA[i]
|
||||
vrshr.s32 q2, q2, #12 // AA[i]
|
||||
|
||||
vst1.32 {q1, q2}, [r0, :128]!
|
||||
vst1.16 {q0}, [r1, :128]!
|
||||
bgt 1b
|
||||
|
||||
vpop {q4-q7}
|
||||
pop {r4-r7,pc}
|
||||
endfunc
|
||||
410
media/libdav1d/src/src/arm/32/looprestoration_tmpl.S
Normal file
410
media/libdav1d/src/src/arm/32/looprestoration_tmpl.S
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2019, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
|
||||
#define FILTER_OUT_STRIDE 384
|
||||
|
||||
.macro sgr_funcs bpc
|
||||
// void dav1d_sgr_finish_filter_row1_Xbpc_neon(int16_t *tmp,
|
||||
// const pixel *src,
|
||||
// const int32_t **a, const int16_t **b,
|
||||
// const int w);
|
||||
function sgr_finish_filter_row1_\bpc\()bpc_neon, export=1
|
||||
push {r4-r11,lr}
|
||||
vpush {q4-q7}
|
||||
ldr r4, [sp, #100]
|
||||
ldrd r6, r7, [r2]
|
||||
ldr r2, [r2, #8]
|
||||
ldrd r8, r9, [r3]
|
||||
ldr r3, [r3, #8]
|
||||
vmov.i16 q14, #3
|
||||
vmov.i32 q15, #3
|
||||
1:
|
||||
vld1.16 {q0}, [r8, :128]!
|
||||
vld1.16 {q1}, [r9, :128]!
|
||||
vld1.16 {q2}, [r3, :128]!
|
||||
vld1.32 {q8, q9}, [r6, :128]!
|
||||
vld1.32 {q10, q11}, [r7, :128]!
|
||||
vld1.32 {q12, q13}, [r2, :128]!
|
||||
|
||||
2:
|
||||
subs r4, r4, #4
|
||||
vext.8 d6, d0, d1, #2 // -stride
|
||||
vext.8 d7, d2, d3, #2 // 0
|
||||
vext.8 d8, d4, d5, #2 // +stride
|
||||
vext.8 d9, d0, d1, #4 // +1-stride
|
||||
vext.8 d10, d2, d3, #4 // +1
|
||||
vext.8 d11, d4, d5, #4 // +1+stride
|
||||
vadd.i16 d2, d2, d6 // -1, -stride
|
||||
vadd.i16 d7, d7, d8 // 0, +stride
|
||||
vadd.i16 d0, d0, d9 // -1-stride, +1-stride
|
||||
vadd.i16 d2, d2, d7
|
||||
vadd.i16 d4, d4, d11 // -1+stride, +1+stride
|
||||
vadd.i16 d2, d2, d10 // +1
|
||||
vadd.i16 d0, d0, d4
|
||||
|
||||
vext.8 q3, q8, q9, #4 // -stride
|
||||
vshl.i16 d2, d2, #2
|
||||
vext.8 q4, q8, q9, #8 // +1-stride
|
||||
vext.8 q5, q10, q11, #4 // 0
|
||||
vext.8 q6, q10, q11, #8 // +1
|
||||
vmla.i16 d2, d0, d28 // * 3 -> a
|
||||
vadd.i32 q3, q3, q10 // -stride, -1
|
||||
vadd.i32 q8, q8, q4 // -1-stride, +1-stride
|
||||
vadd.i32 q5, q5, q6 // 0, +1
|
||||
vadd.i32 q8, q8, q12 // -1+stride
|
||||
vadd.i32 q3, q3, q5
|
||||
vext.8 q7, q12, q13, #4 // +stride
|
||||
vext.8 q10, q12, q13, #8 // +1+stride
|
||||
.if \bpc == 8
|
||||
vld1.32 {d24[0]}, [r1, :32]! // src
|
||||
.else
|
||||
vld1.16 {d24}, [r1, :64]! // src
|
||||
.endif
|
||||
vadd.i32 q3, q3, q7 // +stride
|
||||
vadd.i32 q8, q8, q10 // +1+stride
|
||||
vshl.i32 q3, q3, #2
|
||||
vmla.i32 q3, q8, q15 // * 3 -> b
|
||||
.if \bpc == 8
|
||||
vmovl.u8 q12, d24 // src
|
||||
.endif
|
||||
vmov d0, d1
|
||||
vmlsl.u16 q3, d2, d24 // b - a * src
|
||||
vmov d2, d3
|
||||
vrshrn.i32 d6, q3, #9
|
||||
vmov d4, d5
|
||||
vst1.16 {d6}, [r0]!
|
||||
|
||||
ble 3f
|
||||
vmov q8, q9
|
||||
vmov q10, q11
|
||||
vmov q12, q13
|
||||
vld1.16 {d1}, [r8, :64]!
|
||||
vld1.16 {d3}, [r9, :64]!
|
||||
vld1.16 {d5}, [r3, :64]!
|
||||
vld1.32 {q9}, [r6, :128]!
|
||||
vld1.32 {q11}, [r7, :128]!
|
||||
vld1.32 {q13}, [r2, :128]!
|
||||
b 2b
|
||||
|
||||
3:
|
||||
vpop {q4-q7}
|
||||
pop {r4-r11,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_finish_filter2_2rows_Xbpc_neon(int16_t *tmp,
|
||||
// const pixel *src, const ptrdiff_t stride,
|
||||
// const int32_t **a, const int16_t **b,
|
||||
// const int w, const int h);
|
||||
function sgr_finish_filter2_2rows_\bpc\()bpc_neon, export=1
|
||||
push {r4-r11,lr}
|
||||
vpush {q4-q7}
|
||||
ldrd r4, r5, [sp, #100]
|
||||
ldr r6, [sp, #108]
|
||||
ldrd r8, r9, [r3]
|
||||
ldrd r10, r11, [r4]
|
||||
mov r7, #2*FILTER_OUT_STRIDE
|
||||
add r2, r1, r2
|
||||
add r7, r7, r0
|
||||
mov lr, r5
|
||||
|
||||
1:
|
||||
vld1.16 {q0, q1}, [r10, :128]!
|
||||
vld1.16 {q2, q3}, [r11, :128]!
|
||||
vld1.32 {q8, q9}, [r8, :128]!
|
||||
vld1.32 {q11, q12}, [r9, :128]!
|
||||
vld1.32 {q10}, [r8, :128]!
|
||||
vld1.32 {q13}, [r9, :128]!
|
||||
|
||||
2:
|
||||
vmov.i16 q14, #5
|
||||
vmov.i16 q15, #6
|
||||
subs r5, r5, #8
|
||||
vext.8 q4, q0, q1, #4 // +1-stride
|
||||
vext.8 q5, q2, q3, #4 // +1+stride
|
||||
vext.8 q6, q0, q1, #2 // -stride
|
||||
vext.8 q7, q2, q3, #2 // +stride
|
||||
vadd.i16 q0, q0, q4 // -1-stride, +1-stride
|
||||
vadd.i16 q5, q2, q5 // -1+stride, +1+stride
|
||||
vadd.i16 q2, q6, q7 // -stride, +stride
|
||||
vadd.i16 q0, q0, q5
|
||||
|
||||
vext.8 q4, q8, q9, #8 // +1-stride
|
||||
vext.8 q5, q9, q10, #8
|
||||
vext.8 q6, q11, q12, #8 // +1+stride
|
||||
vext.8 q7, q12, q13, #8
|
||||
vmul.i16 q0, q0, q14 // * 5
|
||||
vmla.i16 q0, q2, q15 // * 6
|
||||
vadd.i32 q4, q4, q8 // -1-stride, +1-stride
|
||||
vadd.i32 q5, q5, q9
|
||||
vadd.i32 q6, q6, q11 // -1+stride, +1+stride
|
||||
vadd.i32 q7, q7, q12
|
||||
vadd.i32 q4, q4, q6
|
||||
vadd.i32 q5, q5, q7
|
||||
vext.8 q6, q8, q9, #4 // -stride
|
||||
vext.8 q7, q9, q10, #4
|
||||
vext.8 q8, q11, q12, #4 // +stride
|
||||
vext.8 q11, q12, q13, #4
|
||||
|
||||
.if \bpc == 8
|
||||
vld1.8 {d4}, [r1, :64]!
|
||||
.else
|
||||
vld1.8 {q2}, [r1, :128]!
|
||||
.endif
|
||||
|
||||
vmov.i32 q14, #5
|
||||
vmov.i32 q15, #6
|
||||
|
||||
vadd.i32 q6, q6, q8 // -stride, +stride
|
||||
vadd.i32 q7, q7, q11
|
||||
vmul.i32 q4, q4, q14 // * 5
|
||||
vmla.i32 q4, q6, q15 // * 6
|
||||
vmul.i32 q5, q5, q14 // * 5
|
||||
vmla.i32 q5, q7, q15 // * 6
|
||||
|
||||
.if \bpc == 8
|
||||
vmovl.u8 q2, d4
|
||||
.endif
|
||||
vmlsl.u16 q4, d0, d4 // b - a * src
|
||||
vmlsl.u16 q5, d1, d5 // b - a * src
|
||||
vmov q0, q1
|
||||
vrshrn.i32 d8, q4, #9
|
||||
vrshrn.i32 d9, q5, #9
|
||||
vmov q2, q3
|
||||
vst1.16 {q4}, [r0, :128]!
|
||||
|
||||
ble 3f
|
||||
vmov q8, q10
|
||||
vmov q11, q13
|
||||
vld1.16 {q1}, [r10, :128]!
|
||||
vld1.16 {q3}, [r11, :128]!
|
||||
vld1.32 {q9, q10}, [r8, :128]!
|
||||
vld1.32 {q12, q13}, [r9, :128]!
|
||||
b 2b
|
||||
|
||||
3:
|
||||
subs r6, r6, #1
|
||||
ble 0f
|
||||
mov r5, lr
|
||||
ldrd r8, r9, [r3]
|
||||
ldrd r10, r11, [r4]
|
||||
mov r0, r7
|
||||
mov r1, r2
|
||||
|
||||
vld1.32 {q8, q9}, [r9, :128]!
|
||||
vld1.16 {q0, q1}, [r11, :128]!
|
||||
vld1.32 {q10}, [r9, :128]!
|
||||
|
||||
vmov.i16 q12, #5
|
||||
vmov.i16 q13, #6
|
||||
|
||||
4:
|
||||
subs r5, r5, #8
|
||||
vext.8 q3, q0, q1, #4 // +1
|
||||
vext.8 q2, q0, q1, #2 // 0
|
||||
vadd.i16 q0, q0, q3 // -1, +1
|
||||
|
||||
vext.8 q4, q8, q9, #4 // 0
|
||||
vext.8 q5, q9, q10, #4
|
||||
vext.8 q6, q8, q9, #8 // +1
|
||||
vext.8 q7, q9, q10, #8
|
||||
vmul.i16 q2, q2, q13 // * 6
|
||||
vmla.i16 q2, q0, q12 // * 5 -> a
|
||||
.if \bpc == 8
|
||||
vld1.8 {d22}, [r1, :64]!
|
||||
.else
|
||||
vld1.16 {q11}, [r1, :128]!
|
||||
.endif
|
||||
vadd.i32 q8, q8, q6 // -1, +1
|
||||
vadd.i32 q9, q9, q7
|
||||
.if \bpc == 8
|
||||
vmovl.u8 q11, d22
|
||||
.endif
|
||||
vmul.i32 q4, q4, q15 // * 6
|
||||
vmla.i32 q4, q8, q14 // * 5 -> b
|
||||
vmul.i32 q5, q5, q15 // * 6
|
||||
vmla.i32 q5, q9, q14 // * 5 -> b
|
||||
|
||||
vmlsl.u16 q4, d4, d22 // b - a * src
|
||||
vmlsl.u16 q5, d5, d23
|
||||
vmov q0, q1
|
||||
vrshrn.i32 d8, q4, #8
|
||||
vrshrn.i32 d9, q5, #8
|
||||
vmov q8, q10
|
||||
vst1.16 {q4}, [r0, :128]!
|
||||
|
||||
ble 5f
|
||||
vld1.16 {q1}, [r11, :128]!
|
||||
vld1.32 {q9, q10}, [r9, :128]!
|
||||
b 4b
|
||||
|
||||
5:
|
||||
0:
|
||||
vpop {q4-q7}
|
||||
pop {r4-r11,pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_weighted_row1_Xbpc_neon(pixel *dst,
|
||||
// const int16_t *t1, const int w,
|
||||
// const int w1, const int bitdepth_max);
|
||||
function sgr_weighted_row1_\bpc\()bpc_neon, export=1
|
||||
push {lr}
|
||||
.if \bpc == 16
|
||||
ldr lr, [sp, #4]
|
||||
.endif
|
||||
vdup.16 d31, r3
|
||||
.if \bpc == 16
|
||||
vmov.i16 q13, #0
|
||||
vdup.16 q14, lr
|
||||
.endif
|
||||
|
||||
1:
|
||||
.if \bpc == 8
|
||||
vld1.8 {d0}, [r0, :64]
|
||||
.else
|
||||
vld1.16 {q0}, [r0, :128]
|
||||
.endif
|
||||
vld1.16 {q1}, [r1, :128]!
|
||||
subs r2, r2, #8
|
||||
vmull.s16 q2, d2, d31 // v
|
||||
vmull.s16 q3, d3, d31 // v
|
||||
vrshrn.i32 d4, q2, #11
|
||||
vrshrn.i32 d5, q3, #11
|
||||
.if \bpc == 8
|
||||
vaddw.u8 q2, q2, d0
|
||||
vqmovun.s16 d2, q2
|
||||
vst1.8 {d2}, [r0, :64]!
|
||||
.else
|
||||
vadd.i16 q2, q2, q0
|
||||
vmax.s16 q2, q2, q13
|
||||
vmin.u16 q2, q2, q14
|
||||
vst1.16 {q2}, [r0, :128]!
|
||||
.endif
|
||||
bgt 1b
|
||||
0:
|
||||
pop {pc}
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_weighted2_Xbpc_neon(pixel *dst, const ptrdiff_t stride,
|
||||
// const int16_t *t1, const int16_t *t2,
|
||||
// const int w, const int h,
|
||||
// const int16_t wt[2], const int bitdepth_max);
|
||||
function sgr_weighted2_\bpc\()bpc_neon, export=1
|
||||
push {r4-r8,lr}
|
||||
ldrd r4, r5, [sp, #24]
|
||||
.if \bpc == 8
|
||||
ldr r6, [sp, #32]
|
||||
.else
|
||||
ldrd r6, r7, [sp, #32]
|
||||
.endif
|
||||
cmp r5, #2
|
||||
add r8, r0, r1
|
||||
add r12, r2, #2*FILTER_OUT_STRIDE
|
||||
add lr, r3, #2*FILTER_OUT_STRIDE
|
||||
vld2.16 {d30[], d31[]}, [r6] // wt[0], wt[1]
|
||||
.if \bpc == 16
|
||||
vdup.16 q14, r7
|
||||
.endif
|
||||
blt 2f
|
||||
1:
|
||||
.if \bpc == 8
|
||||
vld1.8 {d0}, [r0, :64]
|
||||
vld1.8 {d16}, [r8, :64]
|
||||
.else
|
||||
vld1.16 {q0}, [r0, :128]
|
||||
vld1.16 {q8}, [r8, :128]
|
||||
.endif
|
||||
vld1.16 {q1}, [r2, :128]!
|
||||
vld1.16 {q9}, [r12, :128]!
|
||||
vld1.16 {q2}, [r3, :128]!
|
||||
vld1.16 {q10}, [lr, :128]!
|
||||
subs r4, r4, #8
|
||||
vmull.s16 q3, d2, d30 // wt[0] * t1
|
||||
vmlal.s16 q3, d4, d31 // wt[1] * t2
|
||||
vmull.s16 q12, d3, d30 // wt[0] * t1
|
||||
vmlal.s16 q12, d5, d31 // wt[1] * t2
|
||||
vmull.s16 q11, d18, d30 // wt[0] * t1
|
||||
vmlal.s16 q11, d20, d31 // wt[1] * t2
|
||||
vmull.s16 q13, d19, d30 // wt[0] * t1
|
||||
vmlal.s16 q13, d21, d31 // wt[1] * t2
|
||||
vrshrn.i32 d6, q3, #11
|
||||
vrshrn.i32 d7, q12, #11
|
||||
vrshrn.i32 d22, q11, #11
|
||||
vrshrn.i32 d23, q13, #11
|
||||
.if \bpc == 8
|
||||
vaddw.u8 q3, q3, d0
|
||||
vaddw.u8 q11, q11, d16
|
||||
vqmovun.s16 d6, q3
|
||||
vqmovun.s16 d22, q11
|
||||
vst1.8 {d6}, [r0, :64]!
|
||||
vst1.8 {d22}, [r8, :64]!
|
||||
.else
|
||||
vmov.i16 q13, #0
|
||||
vadd.i16 q3, q3, q0
|
||||
vadd.i16 q11, q11, q8
|
||||
vmax.s16 q3, q3, q13
|
||||
vmax.s16 q11, q11, q13
|
||||
vmin.u16 q3, q3, q14
|
||||
vmin.u16 q11, q11, q14
|
||||
vst1.16 {q3}, [r0, :128]!
|
||||
vst1.16 {q11}, [r8, :128]!
|
||||
.endif
|
||||
bgt 1b
|
||||
b 0f
|
||||
|
||||
2:
|
||||
.if \bpc == 8
|
||||
vld1.8 {d0}, [r0, :64]
|
||||
.else
|
||||
vld1.16 {q0}, [r0, :128]
|
||||
.endif
|
||||
vld1.16 {q1}, [r2, :128]!
|
||||
vld1.16 {q2}, [r3, :128]!
|
||||
subs r4, r4, #8
|
||||
vmull.s16 q3, d2, d30 // wt[0] * t1
|
||||
vmlal.s16 q3, d4, d31 // wt[1] * t2
|
||||
vmull.s16 q11, d3, d30 // wt[0] * t1
|
||||
vmlal.s16 q11, d5, d31 // wt[1] * t2
|
||||
vrshrn.i32 d6, q3, #11
|
||||
vrshrn.i32 d7, q11, #11
|
||||
.if \bpc == 8
|
||||
vaddw.u8 q3, q3, d0
|
||||
vqmovun.s16 d6, q3
|
||||
vst1.8 {d6}, [r0, :64]!
|
||||
.else
|
||||
vmov.i16 q13, #0
|
||||
vadd.i16 q3, q3, q0
|
||||
vmax.s16 q3, q3, q13
|
||||
vmin.u16 q3, q3, q14
|
||||
vst1.16 {q3}, [r0, :128]!
|
||||
.endif
|
||||
bgt 2b
|
||||
0:
|
||||
pop {r4-r8,pc}
|
||||
endfunc
|
||||
.endm
|
||||
3340
media/libdav1d/src/src/arm/32/mc.S
Normal file
3340
media/libdav1d/src/src/arm/32/mc.S
Normal file
File diff suppressed because it is too large
Load diff
3658
media/libdav1d/src/src/arm/32/mc16.S
Normal file
3658
media/libdav1d/src/src/arm/32/mc16.S
Normal file
File diff suppressed because it is too large
Load diff
588
media/libdav1d/src/src/arm/32/msac.S
Normal file
588
media/libdav1d/src/src/arm/32/msac.S
Normal file
|
|
@ -0,0 +1,588 @@
|
|||
/*
|
||||
* Copyright © 2019, VideoLAN and dav1d authors
|
||||
* Copyright © 2020, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
#define BUF_POS 0
|
||||
#define BUF_END 4
|
||||
#define DIF 8
|
||||
#define RNG 12
|
||||
#define CNT 16
|
||||
#define ALLOW_UPDATE_CDF 20
|
||||
|
||||
const coeffs
|
||||
.short 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0
|
||||
.short 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
endconst
|
||||
|
||||
const bits, align=4
|
||||
.short 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
|
||||
.short 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000
|
||||
endconst
|
||||
|
||||
.macro vld1_align_n d0, q0, q1, src, n
|
||||
.if \n == 4
|
||||
vld1.16 {\d0}, [\src, :64]
|
||||
.elseif \n == 8
|
||||
vld1.16 {\q0}, [\src, :128]
|
||||
.else
|
||||
vld1.16 {\q0, \q1}, [\src, :128]
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vld1_n d0, q0, q1, src, n
|
||||
.if \n == 4
|
||||
vld1.16 {\d0}, [\src]
|
||||
.elseif \n == 8
|
||||
vld1.16 {\q0}, [\src]
|
||||
.else
|
||||
vld1.16 {\q0, \q1}, [\src]
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vst1_align_n d0, q0, q1, src, n
|
||||
.if \n == 4
|
||||
vst1.16 {\d0}, [\src, :64]
|
||||
.elseif \n == 8
|
||||
vst1.16 {\q0}, [\src, :128]
|
||||
.else
|
||||
vst1.16 {\q0, \q1}, [\src, :128]
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vst1_n d0, q0, q1, src, n
|
||||
.if \n == 4
|
||||
vst1.16 {\d0}, [\src]
|
||||
.elseif \n == 8
|
||||
vst1.16 {\q0}, [\src]
|
||||
.else
|
||||
vst1.16 {\q0, \q1}, [\src]
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vshr_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n
|
||||
.if \n == 4
|
||||
vshr.u16 \d0, \s0, \s3
|
||||
.else
|
||||
vshr.u16 \d1, \s1, \s4
|
||||
.if \n == 16
|
||||
vshr.u16 \d2, \s2, \s5
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vadd_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n
|
||||
.if \n == 4
|
||||
vadd.i16 \d0, \s0, \s3
|
||||
.else
|
||||
vadd.i16 \d1, \s1, \s4
|
||||
.if \n == 16
|
||||
vadd.i16 \d2, \s2, \s5
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vsub_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n
|
||||
.if \n == 4
|
||||
vsub.i16 \d0, \s0, \s3
|
||||
.else
|
||||
vsub.i16 \d1, \s1, \s4
|
||||
.if \n == 16
|
||||
vsub.i16 \d2, \s2, \s5
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vand_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n
|
||||
.if \n == 4
|
||||
vand \d0, \s0, \s3
|
||||
.else
|
||||
vand \d1, \s1, \s4
|
||||
.if \n == 16
|
||||
vand \d2, \s2, \s5
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vcge_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n
|
||||
.if \n == 4
|
||||
vcge.u16 \d0, \s0, \s3
|
||||
.else
|
||||
vcge.u16 \d1, \s1, \s4
|
||||
.if \n == 16
|
||||
vcge.u16 \d2, \s2, \s5
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vrhadd_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n
|
||||
.if \n == 4
|
||||
vrhadd.u16 \d0, \s0, \s3
|
||||
.else
|
||||
vrhadd.u16 \d1, \s1, \s4
|
||||
.if \n == 16
|
||||
vrhadd.u16 \d2, \s2, \s5
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vshl_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n
|
||||
.if \n == 4
|
||||
vshl.s16 \d0, \s0, \s3
|
||||
.else
|
||||
vshl.s16 \d1, \s1, \s4
|
||||
.if \n == 16
|
||||
vshl.s16 \d2, \s2, \s5
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro vqdmulh_n d0, d1, d2, s0, s1, s2, s3, s4, s5, n
|
||||
.if \n == 4
|
||||
vqdmulh.s16 \d0, \s0, \s3
|
||||
.else
|
||||
vqdmulh.s16 \d1, \s1, \s4
|
||||
.if \n == 16
|
||||
vqdmulh.s16 \d2, \s2, \s5
|
||||
.endif
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// unsigned dav1d_msac_decode_symbol_adapt4_neon(MsacContext *s, uint16_t *cdf,
|
||||
// size_t n_symbols);
|
||||
|
||||
function msac_decode_symbol_adapt4_neon, export=1
|
||||
.macro decode_update n
|
||||
push {r4-r10,lr}
|
||||
sub sp, sp, #48
|
||||
add r8, r0, #RNG
|
||||
|
||||
vld1_align_n d0, q0, q1, r1, \n // cdf
|
||||
vld1.16 {d16[]}, [r8, :16] // rng
|
||||
movrel_local r9, coeffs, 30
|
||||
vmov.i16 d30, #0x7f00 // 0x7f00
|
||||
sub r9, r9, r2, lsl #1
|
||||
vmvn.i16 q14, #0x3f // 0xffc0
|
||||
add r8, sp, #14
|
||||
vand d22, d16, d30 // rng & 0x7f00
|
||||
vst1.16 {d16[0]}, [r8, :16] // store original u = s->rng
|
||||
vand_n d4, q2, q3, d0, q0, q1, d28, q14, q14, \n // cdf & 0xffc0
|
||||
.if \n > 4
|
||||
vmov d23, d22
|
||||
.endif
|
||||
|
||||
vld1_n d16, q8, q9, r9, \n // EC_MIN_PROB * (n_symbols - ret)
|
||||
vqdmulh_n d20, q10, q11, d4, q2, q3, d22, q11, q11, \n // ((cdf >> EC_PROB_SHIFT) * (r - 128)) >> 1
|
||||
add r8, r0, #DIF + 2
|
||||
|
||||
vadd_n d16, q8, q9, d4, q2, q3, d16, q8, q9, \n // v = cdf + EC_MIN_PROB * (n_symbols - ret)
|
||||
.if \n == 4
|
||||
vmov.i16 d17, #0
|
||||
.endif
|
||||
vadd_n d16, q8, q9, d20, q10, q11, d16, q8, q9, \n // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret)
|
||||
|
||||
add r9, sp, #16
|
||||
vld1.16 {d20[]}, [r8, :16] // dif >> (EC_WIN_SIZE - 16)
|
||||
movrel_local r8, bits
|
||||
vst1_n q8, q8, q9, r9, \n // store v values to allow indexed access
|
||||
|
||||
vmov d21, d20
|
||||
vld1_align_n q12, q12, q13, r8, \n
|
||||
.if \n == 16
|
||||
vmov q11, q10
|
||||
.endif
|
||||
|
||||
vcge_n q2, q2, q3, q10, q10, q11, q8, q8, q9, \n // c >= v
|
||||
|
||||
vand_n q10, q10, q11, q2, q2, q3, q12, q12, q13, \n // One bit per halfword set in the mask
|
||||
.if \n == 16
|
||||
vadd.i16 q10, q10, q11
|
||||
.endif
|
||||
vadd.i16 d20, d20, d21 // Aggregate mask bits
|
||||
ldr r4, [r0, #ALLOW_UPDATE_CDF]
|
||||
vpadd.i16 d20, d20, d20
|
||||
lsl r10, r2, #1
|
||||
vpadd.i16 d20, d20, d20
|
||||
vmov.u16 r3, d20[0]
|
||||
cmp r4, #0
|
||||
rbit r3, r3
|
||||
clz lr, r3 // ret
|
||||
|
||||
beq L(renorm)
|
||||
// update_cdf
|
||||
ldrh r3, [r1, r10] // count = cdf[n_symbols]
|
||||
vmov.i8 q10, #0xff
|
||||
.if \n == 16
|
||||
mov r4, #-5
|
||||
.else
|
||||
mvn r12, r2
|
||||
mov r4, #-4
|
||||
cmn r12, #3 // set C if n_symbols <= 2
|
||||
.endif
|
||||
vrhadd_n d16, q8, q9, d20, q10, q10, d4, q2, q3, \n // i >= val ? -1 : 32768
|
||||
.if \n == 16
|
||||
sub r4, r4, r3, lsr #4 // -((count >> 4) + 5)
|
||||
.else
|
||||
lsr r12, r3, #4 // count >> 4
|
||||
sbc r4, r4, r12 // -((count >> 4) + (n_symbols > 2) + 4)
|
||||
.endif
|
||||
vsub_n d16, q8, q9, d16, q8, q9, d0, q0, q1, \n // (32768 - cdf[i]) or (-1 - cdf[i])
|
||||
.if \n == 4
|
||||
vdup.16 d20, r4 // -rate
|
||||
.else
|
||||
vdup.16 q10, r4 // -rate
|
||||
.endif
|
||||
|
||||
sub r3, r3, r3, lsr #5 // count - (count == 32)
|
||||
vsub_n d0, q0, q1, d0, q0, q1, d4, q2, q3, \n // cdf + (i >= val ? 1 : 0)
|
||||
vshl_n d16, q8, q9, d16, q8, q9, d20, q10, q10, \n // ({32768,-1} - cdf[i]) >> rate
|
||||
add r3, r3, #1 // count + (count < 32)
|
||||
vadd_n d0, q0, q1, d0, q0, q1, d16, q8, q9, \n // cdf + (32768 - cdf[i]) >> rate
|
||||
vst1_align_n d0, q0, q1, r1, \n
|
||||
strh r3, [r1, r10]
|
||||
.endm
|
||||
|
||||
decode_update 4
|
||||
|
||||
L(renorm):
|
||||
add r8, sp, #16
|
||||
add r8, r8, lr, lsl #1
|
||||
ldrh r3, [r8] // v
|
||||
ldrh r4, [r8, #-2] // u
|
||||
ldr r6, [r0, #CNT]
|
||||
ldr r7, [r0, #DIF]
|
||||
sub r4, r4, r3 // rng = u - v
|
||||
clz r5, r4 // clz(rng)
|
||||
eor r5, r5, #16 // d = clz(rng) ^ 16
|
||||
sub r7, r7, r3, lsl #16 // dif - (v << 16)
|
||||
L(renorm2):
|
||||
lsl r4, r4, r5 // rng << d
|
||||
subs r6, r6, r5 // cnt -= d
|
||||
lsl r7, r7, r5 // (dif - (v << 16)) << d
|
||||
str r4, [r0, #RNG]
|
||||
bhs 4f
|
||||
|
||||
// refill
|
||||
ldr r3, [r0, #BUF_POS] // BUF_POS
|
||||
ldr r4, [r0, #BUF_END] // BUF_END
|
||||
add r5, r3, #4
|
||||
subs r5, r5, r4
|
||||
bhi 6f
|
||||
|
||||
ldr r8, [r3] // next_bits
|
||||
rsb r5, r6, #16
|
||||
add r4, r6, #16 // shift_bits = cnt + 16
|
||||
mvn r8, r8
|
||||
lsr r5, r5, #3 // num_bytes_read
|
||||
rev r8, r8 // next_bits = bswap(next_bits)
|
||||
lsr r8, r8, r4 // next_bits >>= shift_bits
|
||||
|
||||
2: // refill_end
|
||||
add r3, r3, r5
|
||||
add r6, r6, r5, lsl #3 // cnt += num_bits_read
|
||||
str r3, [r0, #BUF_POS]
|
||||
|
||||
3: // refill_end2
|
||||
orr r7, r7, r8 // dif |= next_bits
|
||||
|
||||
4: // end
|
||||
str r6, [r0, #CNT]
|
||||
str r7, [r0, #DIF]
|
||||
mov r0, lr
|
||||
add sp, sp, #48
|
||||
pop {r4-r10,pc}
|
||||
|
||||
5: // pad_with_ones
|
||||
add r8, r6, #-240
|
||||
lsr r8, r8, r8
|
||||
b 3b
|
||||
|
||||
6: // refill_eob
|
||||
cmp r3, r4
|
||||
bhs 5b
|
||||
|
||||
ldr r8, [r4, #-4]
|
||||
lsl r5, r5, #3
|
||||
lsr r8, r8, r5
|
||||
add r5, r6, #16
|
||||
mvn r8, r8
|
||||
sub r4, r4, r3 // num_bytes_left
|
||||
rev r8, r8
|
||||
lsr r8, r8, r5
|
||||
rsb r5, r6, #16
|
||||
lsr r5, r5, #3
|
||||
cmp r5, r4
|
||||
it hs
|
||||
movhs r5, r4
|
||||
b 2b
|
||||
endfunc
|
||||
|
||||
function msac_decode_symbol_adapt8_neon, export=1
|
||||
decode_update 8
|
||||
b L(renorm)
|
||||
endfunc
|
||||
|
||||
function msac_decode_symbol_adapt16_neon, export=1
|
||||
decode_update 16
|
||||
b L(renorm)
|
||||
endfunc
|
||||
|
||||
function msac_decode_hi_tok_neon, export=1
|
||||
push {r4-r10,lr}
|
||||
vld1.16 {d0}, [r1, :64] // cdf
|
||||
add r4, r0, #RNG
|
||||
vmov.i16 d31, #0x7f00 // 0x7f00
|
||||
movrel_local r5, coeffs, 30-2*3
|
||||
vmvn.i16 d30, #0x3f // 0xffc0
|
||||
ldrh r9, [r1, #6] // count = cdf[n_symbols]
|
||||
vld1.16 {d1[]}, [r4, :16] // rng
|
||||
movrel_local r4, bits
|
||||
vld1.16 {d29}, [r5] // EC_MIN_PROB * (n_symbols - ret)
|
||||
add r5, r0, #DIF + 2
|
||||
vld1.16 {q8}, [r4, :128]
|
||||
mov r2, #-24
|
||||
vand d20, d0, d30 // cdf & 0xffc0
|
||||
ldr r10, [r0, #ALLOW_UPDATE_CDF]
|
||||
vld1.16 {d2[]}, [r5, :16] // dif >> (EC_WIN_SIZE - 16)
|
||||
sub sp, sp, #48
|
||||
ldr r6, [r0, #CNT]
|
||||
ldr r7, [r0, #DIF]
|
||||
vmov d3, d2
|
||||
1:
|
||||
vand d23, d1, d31 // rng & 0x7f00
|
||||
vqdmulh.s16 d18, d20, d23 // ((cdf >> EC_PROB_SHIFT) * (r - 128)) >> 1
|
||||
add r12, sp, #14
|
||||
vadd.i16 d6, d20, d29 // v = cdf + EC_MIN_PROB * (n_symbols - ret)
|
||||
vadd.i16 d6, d18, d6 // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret)
|
||||
vmov.i16 d7, #0
|
||||
vst1.16 {d1[0]}, [r12, :16] // store original u = s->rng
|
||||
add r12, sp, #16
|
||||
vcge.u16 q2, q1, q3 // c >= v
|
||||
vst1.16 {q3}, [r12] // store v values to allow indexed access
|
||||
vand q9, q2, q8 // One bit per halfword set in the mask
|
||||
|
||||
vadd.i16 d18, d18, d19 // Aggregate mask bits
|
||||
vpadd.i16 d18, d18, d18
|
||||
vpadd.i16 d18, d18, d18
|
||||
vmov.u16 r3, d18[0]
|
||||
cmp r10, #0
|
||||
add r2, r2, #5
|
||||
rbit r3, r3
|
||||
add r8, sp, #16
|
||||
clz lr, r3 // ret
|
||||
|
||||
beq 2f
|
||||
// update_cdf
|
||||
vmov.i8 d22, #0xff
|
||||
mov r4, #-5
|
||||
vrhadd.u16 d6, d22, d4 // i >= val ? -1 : 32768
|
||||
sub r4, r4, r9, lsr #4 // -((count >> 4) + 5)
|
||||
vsub.i16 d6, d6, d0 // (32768 - cdf[i]) or (-1 - cdf[i])
|
||||
vdup.16 d18, r4 // -rate
|
||||
|
||||
sub r9, r9, r9, lsr #5 // count - (count == 32)
|
||||
vsub.i16 d0, d0, d4 // cdf + (i >= val ? 1 : 0)
|
||||
vshl.s16 d6, d6, d18 // ({32768,-1} - cdf[i]) >> rate
|
||||
add r9, r9, #1 // count + (count < 32)
|
||||
vadd.i16 d0, d0, d6 // cdf + (32768 - cdf[i]) >> rate
|
||||
vst1.16 {d0}, [r1, :64]
|
||||
vand d20, d0, d30 // cdf & 0xffc0
|
||||
strh r9, [r1, #6]
|
||||
|
||||
2:
|
||||
add r8, r8, lr, lsl #1
|
||||
ldrh r3, [r8] // v
|
||||
ldrh r4, [r8, #-2] // u
|
||||
sub r4, r4, r3 // rng = u - v
|
||||
clz r5, r4 // clz(rng)
|
||||
eor r5, r5, #16 // d = clz(rng) ^ 16
|
||||
sub r7, r7, r3, lsl #16 // dif - (v << 16)
|
||||
lsl r4, r4, r5 // rng << d
|
||||
subs r6, r6, r5 // cnt -= d
|
||||
lsl r7, r7, r5 // (dif - (v << 16)) << d
|
||||
str r4, [r0, #RNG]
|
||||
vdup.16 d1, r4
|
||||
bhs 5f
|
||||
|
||||
// refill
|
||||
ldr r3, [r0, #BUF_POS] // BUF_POS
|
||||
ldr r4, [r0, #BUF_END] // BUF_END
|
||||
add r5, r3, #4
|
||||
subs r5, r5, r4
|
||||
bhi 7f
|
||||
|
||||
ldr r8, [r3] // next_bits
|
||||
rsb r5, r6, #16
|
||||
add r4, r6, #16 // shift_bits = cnt + 16
|
||||
mvn r8, r8
|
||||
lsr r5, r5, #3 // num_bytes_read
|
||||
rev r8, r8 // next_bits = bswap(next_bits)
|
||||
lsr r8, r8, r4 // next_bits >>= shift_bits
|
||||
|
||||
3: // refill_end
|
||||
add r3, r3, r5
|
||||
add r6, r6, r5, lsl #3 // cnt += num_bits_read
|
||||
str r3, [r0, #BUF_POS]
|
||||
|
||||
4: // refill_end2
|
||||
orr r7, r7, r8 // dif |= next_bits
|
||||
|
||||
5: // end
|
||||
lsl lr, lr, #1
|
||||
sub lr, lr, #5
|
||||
lsr r12, r7, #16
|
||||
adds r2, r2, lr // carry = tok_br < 3 || tok == 15
|
||||
vdup.16 q1, r12
|
||||
bcc 1b // loop if !carry
|
||||
add r2, r2, #30
|
||||
str r6, [r0, #CNT]
|
||||
add sp, sp, #48
|
||||
str r7, [r0, #DIF]
|
||||
lsr r0, r2, #1
|
||||
pop {r4-r10,pc}
|
||||
|
||||
6: // pad_with_ones
|
||||
add r8, r6, #-240
|
||||
lsr r8, r8, r8
|
||||
b 4b
|
||||
|
||||
7: // refill_eob
|
||||
cmp r3, r4
|
||||
bhs 6b
|
||||
|
||||
ldr r8, [r4, #-4]
|
||||
lsl r5, r5, #3
|
||||
lsr r8, r8, r5
|
||||
add r5, r6, #16
|
||||
mvn r8, r8
|
||||
sub r4, r4, r3 // num_bytes_left
|
||||
rev r8, r8
|
||||
lsr r8, r8, r5
|
||||
rsb r5, r6, #16
|
||||
lsr r5, r5, #3
|
||||
cmp r5, r4
|
||||
it hs
|
||||
movhs r5, r4
|
||||
b 3b
|
||||
endfunc
|
||||
|
||||
function msac_decode_bool_equi_neon, export=1
|
||||
push {r4-r10,lr}
|
||||
ldr r5, [r0, #RNG]
|
||||
ldr r6, [r0, #CNT]
|
||||
sub sp, sp, #48
|
||||
ldr r7, [r0, #DIF]
|
||||
bic r4, r5, #0xff // r &= 0xff00
|
||||
add r4, r4, #8
|
||||
mov r2, #0
|
||||
subs r8, r7, r4, lsl #15 // dif - vw
|
||||
lsr r4, r4, #1 // v
|
||||
sub r5, r5, r4 // r - v
|
||||
itee lo
|
||||
movlo r2, #1
|
||||
movhs r4, r5 // if (ret) v = r - v;
|
||||
movhs r7, r8 // if (ret) dif = dif - vw;
|
||||
|
||||
clz r5, r4 // clz(rng)
|
||||
eor r5, r5, #16 // d = clz(rng) ^ 16
|
||||
mov lr, r2
|
||||
b L(renorm2)
|
||||
endfunc
|
||||
|
||||
function msac_decode_bool_neon, export=1
|
||||
push {r4-r10,lr}
|
||||
ldr r5, [r0, #RNG]
|
||||
ldr r6, [r0, #CNT]
|
||||
sub sp, sp, #48
|
||||
ldr r7, [r0, #DIF]
|
||||
lsr r4, r5, #8 // r >> 8
|
||||
bic r1, r1, #0x3f // f &= ~63
|
||||
mul r4, r4, r1
|
||||
mov r2, #0
|
||||
lsr r4, r4, #7
|
||||
add r4, r4, #4 // v
|
||||
subs r8, r7, r4, lsl #16 // dif - vw
|
||||
sub r5, r5, r4 // r - v
|
||||
itee lo
|
||||
movlo r2, #1
|
||||
movhs r4, r5 // if (ret) v = r - v;
|
||||
movhs r7, r8 // if (ret) dif = dif - vw;
|
||||
|
||||
clz r5, r4 // clz(rng)
|
||||
eor r5, r5, #16 // d = clz(rng) ^ 16
|
||||
mov lr, r2
|
||||
b L(renorm2)
|
||||
endfunc
|
||||
|
||||
function msac_decode_bool_adapt_neon, export=1
|
||||
push {r4-r10,lr}
|
||||
ldr r9, [r1] // cdf[0-1]
|
||||
ldr r5, [r0, #RNG]
|
||||
movw lr, #0xffc0
|
||||
ldr r6, [r0, #CNT]
|
||||
sub sp, sp, #48
|
||||
ldr r7, [r0, #DIF]
|
||||
lsr r4, r5, #8 // r >> 8
|
||||
and r2, r9, lr // f &= ~63
|
||||
mul r4, r4, r2
|
||||
mov r2, #0
|
||||
lsr r4, r4, #7
|
||||
add r4, r4, #4 // v
|
||||
subs r8, r7, r4, lsl #16 // dif - vw
|
||||
sub r5, r5, r4 // r - v
|
||||
ldr r10, [r0, #ALLOW_UPDATE_CDF]
|
||||
itee lo
|
||||
movlo r2, #1
|
||||
movhs r4, r5 // if (ret) v = r - v;
|
||||
movhs r7, r8 // if (ret) dif = dif - vw;
|
||||
|
||||
cmp r10, #0
|
||||
clz r5, r4 // clz(rng)
|
||||
eor r5, r5, #16 // d = clz(rng) ^ 16
|
||||
mov lr, r2
|
||||
|
||||
beq L(renorm2)
|
||||
|
||||
lsr r2, r9, #16 // count = cdf[1]
|
||||
uxth r9, r9 // cdf[0]
|
||||
|
||||
sub r3, r2, r2, lsr #5 // count - (count >= 32)
|
||||
lsr r2, r2, #4 // count >> 4
|
||||
add r10, r3, #1 // count + (count < 32)
|
||||
add r2, r2, #4 // rate = (count >> 4) | 4
|
||||
|
||||
sub r9, r9, lr // cdf[0] -= bit
|
||||
sub r3, r9, lr, lsl #15 // {cdf[0], cdf[0] - 32769}
|
||||
asr r3, r3, r2 // {cdf[0], cdf[0] - 32769} >> rate
|
||||
sub r9, r9, r3 // cdf[0]
|
||||
|
||||
strh r9, [r1]
|
||||
strh r10, [r1, #2]
|
||||
|
||||
b L(renorm2)
|
||||
endfunc
|
||||
303
media/libdav1d/src/src/arm/32/refmvs.S
Normal file
303
media/libdav1d/src/src/arm/32/refmvs.S
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* Copyright © 2021, VideoLAN and dav1d authors
|
||||
* Copyright © 2021, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
// void dav1d_splat_mv_neon(refmvs_block **rr, const refmvs_block *rmv,
|
||||
// int bx4, int bw4, int bh4)
|
||||
|
||||
function splat_mv_neon, export=1
|
||||
push {r4, lr}
|
||||
vld1.8 {q3}, [r1]
|
||||
ldr r4, [sp, #8]
|
||||
clz r3, r3
|
||||
adr lr, L(splat_tbl)
|
||||
sub r3, r3, #26
|
||||
vext.8 q2, q3, q3, #12
|
||||
ldr r3, [lr, r3, lsl #2]
|
||||
add r2, r2, r2, lsl #1
|
||||
vext.8 q0, q2, q3, #4
|
||||
add r3, lr, r3
|
||||
vext.8 q1, q2, q3, #8
|
||||
lsl r2, r2, #2
|
||||
vext.8 q2, q2, q3, #12
|
||||
vmov q3, q0
|
||||
1:
|
||||
ldr r1, [r0], #4
|
||||
subs r4, r4, #1
|
||||
add r1, r1, r2
|
||||
bx r3
|
||||
|
||||
.align 2
|
||||
L(splat_tbl):
|
||||
.word 320f - L(splat_tbl) + CONFIG_THUMB
|
||||
.word 160f - L(splat_tbl) + CONFIG_THUMB
|
||||
.word 80f - L(splat_tbl) + CONFIG_THUMB
|
||||
.word 40f - L(splat_tbl) + CONFIG_THUMB
|
||||
.word 20f - L(splat_tbl) + CONFIG_THUMB
|
||||
.word 10f - L(splat_tbl) + CONFIG_THUMB
|
||||
|
||||
10:
|
||||
vst1.8 {d0}, [r1]
|
||||
vstr s2, [r1, #8]
|
||||
bgt 1b
|
||||
pop {r4, pc}
|
||||
20:
|
||||
vst1.8 {q0}, [r1]
|
||||
vstr d2, [r1, #16]
|
||||
bgt 1b
|
||||
pop {r4, pc}
|
||||
40:
|
||||
vst1.8 {q0, q1}, [r1]!
|
||||
vst1.8 {q2}, [r1]
|
||||
bgt 1b
|
||||
pop {r4, pc}
|
||||
320:
|
||||
vst1.8 {q0, q1}, [r1]!
|
||||
vst1.8 {q2, q3}, [r1]!
|
||||
vst1.8 {q1, q2}, [r1]!
|
||||
vst1.8 {q0, q1}, [r1]!
|
||||
vst1.8 {q2, q3}, [r1]!
|
||||
vst1.8 {q1, q2}, [r1]!
|
||||
160:
|
||||
vst1.8 {q0, q1}, [r1]!
|
||||
vst1.8 {q2, q3}, [r1]!
|
||||
vst1.8 {q1, q2}, [r1]!
|
||||
80:
|
||||
vst1.8 {q0, q1}, [r1]!
|
||||
vst1.8 {q2, q3}, [r1]!
|
||||
vst1.8 {q1, q2}, [r1]
|
||||
bgt 1b
|
||||
pop {r4, pc}
|
||||
endfunc
|
||||
|
||||
const mv_tbls, align=4
|
||||
.byte 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
|
||||
.byte 0, 1, 2, 3, 8, 0, 1, 2, 3, 8, 0, 1, 2, 3, 8, 0
|
||||
.byte 4, 5, 6, 7, 9, 4, 5, 6, 7, 9, 4, 5, 6, 7, 9, 4
|
||||
.byte 4, 5, 6, 7, 9, 4, 5, 6, 7, 9, 4, 5, 6, 7, 9, 4
|
||||
endconst
|
||||
|
||||
const mask_mult, align=4
|
||||
.byte 1, 2, 1, 2, 0, 0, 0, 0
|
||||
endconst
|
||||
|
||||
// void dav1d_save_tmvs_neon(refmvs_temporal_block *rp, ptrdiff_t stride,
|
||||
// refmvs_block **rr, const uint8_t *ref_sign,
|
||||
// int col_end8, int row_end8,
|
||||
// int col_start8, int row_start8)
|
||||
function save_tmvs_neon, export=1
|
||||
push {r4-r11,lr}
|
||||
ldrd r4, r5, [sp, #36]
|
||||
ldrd r6, r7, [sp, #44]
|
||||
|
||||
vmov.i8 d30, #0
|
||||
vld1.8 {d31}, [r3]
|
||||
adr r8, L(save_tmvs_tbl)
|
||||
movrel_local lr, mask_mult
|
||||
movrel_local r12, mv_tbls
|
||||
vld1.8 {d29}, [lr]
|
||||
vext.8 d31, d30, d31, #7 // [0, ref_sign]
|
||||
mov r3, #5
|
||||
mul r1, r1, r3 // stride *= 5
|
||||
sub r5, r5, r7 // h = row_end8 - row_start8
|
||||
lsl r7, r7, #1 // row_start8 <<= 1
|
||||
1:
|
||||
mov r3, #5
|
||||
mov r11, #12*2
|
||||
and r9, r7, #30 // (y & 15) * 2
|
||||
ldr r9, [r2, r9, lsl #2] // b = rr[(y & 15) * 2]
|
||||
add r9, r9, #12 // &b[... + 1]
|
||||
mla r10, r4, r11, r9 // end_cand_b = &b[col_end8*2 + 1]
|
||||
mla r9, r6, r11, r9 // cand_b = &b[x*2 + 1]
|
||||
|
||||
mla r3, r6, r3, r0 // &rp[x]
|
||||
|
||||
push {r2,r4,r6}
|
||||
|
||||
2:
|
||||
ldrb r11, [r9, #10] // cand_b->bs
|
||||
add lr, r9, #8
|
||||
vld1.8 {d0, d1}, [r9] // cand_b->mv
|
||||
add r11, r8, r11, lsl #3
|
||||
vld1.16 {d2[]}, [lr] // cand_b->ref
|
||||
ldrh lr, [r11] // bw8
|
||||
mov r2, r8
|
||||
add r9, r9, lr, lsl #1 // cand_b += bw8*2
|
||||
cmp r9, r10
|
||||
vmov d4, d0
|
||||
bge 3f
|
||||
|
||||
ldrb r2, [r9, #10] // cand_b->bs
|
||||
add lr, r9, #8
|
||||
vld1.8 {d6, d7}, [r9] // cand_b->mv
|
||||
add r2, r8, r2, lsl #3
|
||||
vld1.16 {d2[1]}, [lr] // cand_b->ref
|
||||
ldrh lr, [r2] // bw8
|
||||
add r9, r9, lr, lsl #1 // cand_b += bw8*2
|
||||
vmov d5, d6
|
||||
|
||||
3:
|
||||
vabs.s16 q2, q2 // abs(mv[].xy)
|
||||
vtbl.8 d2, {d31}, d2 // ref_sign[ref]
|
||||
vshr.u16 q2, q2, #12 // abs(mv[].xy) >> 12
|
||||
vmull.u8 q1, d2, d29 // ref_sign[ref] * {1, 2}
|
||||
vceq.i32 q2, q2, #0 // abs(mv[].xy) <= 4096
|
||||
vmovn.i32 d4, q2 // abs() condition to 16 bit
|
||||
vand d2, d2, d4 // h[0-3] contains conditions for mv[0-1]
|
||||
vpadd.i16 d2, d2, d2 // Combine condition for [1] and [0]
|
||||
vmov.u16 r4, d2[0] // Extract case for first block
|
||||
vmov.u16 r6, d2[1]
|
||||
ldr r11, [r11, #4] // Fetch jump table entry
|
||||
ldr r2, [r2, #4]
|
||||
add r4, r12, r4, lsl #4
|
||||
add r6, r12, r6, lsl #4
|
||||
vld1.8 {d2, d3}, [r4] // Load permutation table base on case
|
||||
vld1.8 {d4, d5}, [r6]
|
||||
add r11, r8, r11 // Find jump table target
|
||||
add r2, r8, r2
|
||||
vtbl.8 d16, {d0, d1}, d2 // Permute cand_b to output refmvs_temporal_block
|
||||
vtbl.8 d17, {d0, d1}, d3
|
||||
vtbl.8 d18, {d6, d7}, d4
|
||||
vtbl.8 d19, {d6, d7}, d5
|
||||
vmov q0, q8
|
||||
|
||||
// q1 follows on q0 (q8), with another 3 full repetitions of the pattern.
|
||||
vext.8 q1, q8, q8, #1
|
||||
vext.8 q10, q9, q9, #1
|
||||
// q2 ends with 3 complete repetitions of the pattern.
|
||||
vext.8 q2, q8, q1, #4
|
||||
vext.8 q11, q9, q10, #4
|
||||
|
||||
blx r11
|
||||
bge 4f // if (cand_b >= end)
|
||||
vmov q0, q9
|
||||
vmov q1, q10
|
||||
vmov q2, q11
|
||||
cmp r9, r10
|
||||
blx r2
|
||||
blt 2b // if (cand_b < end)
|
||||
|
||||
4:
|
||||
pop {r2,r4,r6}
|
||||
|
||||
subs r5, r5, #1 // h--
|
||||
add r7, r7, #2 // y += 2
|
||||
add r0, r0, r1 // rp += stride
|
||||
bgt 1b
|
||||
|
||||
pop {r4-r11,pc}
|
||||
|
||||
.align 2
|
||||
L(save_tmvs_tbl):
|
||||
.word 16 * 12
|
||||
.word 160f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 16 * 12
|
||||
.word 160f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 8 * 12
|
||||
.word 80f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 8 * 12
|
||||
.word 80f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 8 * 12
|
||||
.word 80f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 8 * 12
|
||||
.word 80f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 4 * 12
|
||||
.word 40f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 4 * 12
|
||||
.word 40f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 4 * 12
|
||||
.word 40f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 4 * 12
|
||||
.word 40f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 2 * 12
|
||||
.word 20f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 2 * 12
|
||||
.word 20f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 2 * 12
|
||||
.word 20f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 2 * 12
|
||||
.word 20f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 2 * 12
|
||||
.word 20f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 1 * 12
|
||||
.word 10f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 1 * 12
|
||||
.word 10f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 1 * 12
|
||||
.word 10f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 1 * 12
|
||||
.word 10f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 1 * 12
|
||||
.word 10f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 1 * 12
|
||||
.word 10f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
.word 1 * 12
|
||||
.word 10f - L(save_tmvs_tbl) + CONFIG_THUMB
|
||||
|
||||
10:
|
||||
add r4, r3, #4
|
||||
vst1.32 {d0[0]}, [r3]
|
||||
vst1.8 {d0[4]}, [r4]
|
||||
add r3, r3, #5
|
||||
bx lr
|
||||
20:
|
||||
add r4, r3, #8
|
||||
vst1.8 {d0}, [r3]
|
||||
vst1.16 {d1[0]}, [r4]
|
||||
add r3, r3, #2*5
|
||||
bx lr
|
||||
40:
|
||||
add r4, r3, #16
|
||||
vst1.8 {q0}, [r3]
|
||||
vst1.32 {d2[0]}, [r4]
|
||||
add r3, r3, #4*5
|
||||
bx lr
|
||||
80:
|
||||
add r4, r3, #(8*5-16)
|
||||
// This writes 6 full entries plus 2 extra bytes
|
||||
vst1.8 {q0, q1}, [r3]
|
||||
// Write the last few, overlapping with the first write.
|
||||
vst1.8 {q2}, [r4]
|
||||
add r3, r3, #8*5
|
||||
bx lr
|
||||
160:
|
||||
add r4, r3, #6*5
|
||||
add r6, r3, #12*5
|
||||
// This writes 6 full entries plus 2 extra bytes
|
||||
vst1.8 {q0, q1}, [r3]
|
||||
// Write another 6 full entries, slightly overlapping with the first set
|
||||
vst1.8 {q0, q1}, [r4]
|
||||
add r4, r3, #(16*5-16)
|
||||
// Write 8 bytes (one full entry) after the first 12
|
||||
vst1.8 {d0}, [r6]
|
||||
// Write the last 3 entries
|
||||
vst1.8 {q2}, [r4]
|
||||
add r3, r3, #16*5
|
||||
bx lr
|
||||
endfunc
|
||||
202
media/libdav1d/src/src/arm/32/util.S
Normal file
202
media/libdav1d/src/src/arm/32/util.S
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/******************************************************************************
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2015 Martin Storsjo
|
||||
* Copyright © 2015 Janne Grunau
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef DAV1D_SRC_ARM_32_UTIL_S
|
||||
#define DAV1D_SRC_ARM_32_UTIL_S
|
||||
|
||||
#include "config.h"
|
||||
#include "src/arm/asm.S"
|
||||
#include "src/arm/arm-arch.h"
|
||||
|
||||
.macro v4bx rd
|
||||
#if __ARM_ARCH >= 5 || defined(__ARM_ARCH_4T__)
|
||||
bx \rd
|
||||
#else
|
||||
mov pc, \rd
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro v4blx rd
|
||||
#if __ARM_ARCH >= 5
|
||||
blx \rd
|
||||
#else
|
||||
mov lr, pc
|
||||
v4bx \rd
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro movrel_local rd, val, offset=0
|
||||
#if (__ARM_ARCH >= 7 || defined(__ARM_ARCH_6T2__)) && !defined(PIC)
|
||||
movw \rd, #:lower16:\val+\offset
|
||||
movt \rd, #:upper16:\val+\offset
|
||||
#else
|
||||
ldr \rd, 90001f
|
||||
b 90002f
|
||||
90001:
|
||||
.word \val + \offset - (90002f + 8 - 4 * CONFIG_THUMB)
|
||||
90002:
|
||||
add \rd, \rd, pc
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro movrel rd, val, offset=0
|
||||
#if defined(PIC) && defined(__APPLE__)
|
||||
ldr \rd, 1f
|
||||
b 2f
|
||||
1:
|
||||
.word 3f - (2f + 8 - 4 * CONFIG_THUMB)
|
||||
2:
|
||||
ldr \rd, [pc, \rd]
|
||||
.if \offset < 0
|
||||
sub \rd, \rd, #-(\offset)
|
||||
.elseif \offset > 0
|
||||
add \rd, \rd, #\offset
|
||||
.endif
|
||||
.non_lazy_symbol_pointer
|
||||
3:
|
||||
.indirect_symbol \val
|
||||
.word 0
|
||||
.text
|
||||
#else
|
||||
movrel_local \rd, \val, \offset
|
||||
#endif
|
||||
.endm
|
||||
|
||||
// This macro clobbers r7 (and r12 on windows) and stores data at the
|
||||
// bottom of the stack; sp is the start of the space allocated that
|
||||
// the caller can use.
|
||||
.macro sub_sp_align space
|
||||
#if CONFIG_THUMB
|
||||
mov r7, sp
|
||||
and r7, r7, #15
|
||||
#else
|
||||
and r7, sp, #15
|
||||
#endif
|
||||
sub sp, sp, r7
|
||||
// Now the stack is aligned, store the amount of adjustment back
|
||||
// on the stack, as we don't want to waste a register as frame
|
||||
// pointer.
|
||||
str r7, [sp, #-16]!
|
||||
#ifdef _WIN32
|
||||
.if \space > 8192
|
||||
// Here, we'd need to touch two (or more) pages while decrementing
|
||||
// the stack pointer.
|
||||
.error "sub_sp_align doesn't support values over 8K at the moment"
|
||||
.elseif \space > 4096
|
||||
sub r7, sp, #4096
|
||||
ldr r12, [r7]
|
||||
sub r7, r7, #(\space - 4096)
|
||||
mov sp, r7
|
||||
.else
|
||||
sub sp, sp, #\space
|
||||
.endif
|
||||
#else
|
||||
.if \space >= 4096
|
||||
sub sp, sp, #(\space)/4096*4096
|
||||
.endif
|
||||
.if (\space % 4096) != 0
|
||||
sub sp, sp, #(\space)%4096
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro add_sp_align space
|
||||
.if \space >= 4096
|
||||
add sp, sp, #(\space)/4096*4096
|
||||
.endif
|
||||
.if (\space % 4096) != 0
|
||||
add sp, sp, #(\space)%4096
|
||||
.endif
|
||||
ldr r7, [sp], #16
|
||||
// Add back the original stack adjustment
|
||||
add sp, sp, r7
|
||||
.endm
|
||||
|
||||
.macro transpose_8x8b q0, q1, q2, q3, r0, r1, r2, r3, r4, r5, r6, r7
|
||||
vtrn.32 \q0, \q2
|
||||
vtrn.32 \q1, \q3
|
||||
|
||||
vtrn.16 \r0, \r2
|
||||
vtrn.16 \r1, \r3
|
||||
vtrn.16 \r4, \r6
|
||||
vtrn.16 \r5, \r7
|
||||
|
||||
vtrn.8 \r0, \r1
|
||||
vtrn.8 \r2, \r3
|
||||
vtrn.8 \r4, \r5
|
||||
vtrn.8 \r6, \r7
|
||||
.endm
|
||||
|
||||
.macro transpose_8x8h r0, r1, r2, r3, r4, r5, r6, r7, d0, d1, d2, d3, d4, d5, d6, d7
|
||||
vswp \d0, \d4
|
||||
vswp \d1, \d5
|
||||
vswp \d2, \d6
|
||||
vswp \d3, \d7
|
||||
|
||||
vtrn.32 \r0, \r2
|
||||
vtrn.32 \r1, \r3
|
||||
vtrn.32 \r4, \r6
|
||||
vtrn.32 \r5, \r7
|
||||
|
||||
vtrn.16 \r0, \r1
|
||||
vtrn.16 \r2, \r3
|
||||
vtrn.16 \r4, \r5
|
||||
vtrn.16 \r6, \r7
|
||||
.endm
|
||||
|
||||
.macro transpose_4x8b q0, q1, r0, r1, r2, r3
|
||||
vtrn.16 \q0, \q1
|
||||
|
||||
vtrn.8 \r0, \r1
|
||||
vtrn.8 \r2, \r3
|
||||
.endm
|
||||
|
||||
.macro transpose_4x4s q0, q1, q2, q3, r0, r1, r2, r3, r4, r5, r6, r7
|
||||
vswp \r1, \r4 // vtrn.64 \q0, \q2
|
||||
vswp \r3, \r6 // vtrn.64 \q1, \q3
|
||||
|
||||
vtrn.32 \q0, \q1
|
||||
vtrn.32 \q2, \q3
|
||||
.endm
|
||||
|
||||
.macro transpose_4x4h q0, q1, r0, r1, r2, r3
|
||||
vtrn.32 \q0, \q1
|
||||
|
||||
vtrn.16 \r0, \r1
|
||||
vtrn.16 \r2, \r3
|
||||
.endm
|
||||
|
||||
.macro transpose_4x8h r0, r1, r2, r3
|
||||
vtrn.32 \r0, \r2
|
||||
vtrn.32 \r1, \r3
|
||||
|
||||
vtrn.16 \r0, \r1
|
||||
vtrn.16 \r2, \r3
|
||||
.endm
|
||||
|
||||
#endif /* DAV1D_SRC_ARM_32_UTIL_S */
|
||||
520
media/libdav1d/src/src/arm/64/cdef.S
Normal file
520
media/libdav1d/src/src/arm/64/cdef.S
Normal file
|
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2019, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
#include "cdef_tmpl.S"
|
||||
|
||||
.macro pad_top_bottom s1, s2, w, stride, rn, rw, ret
|
||||
tst w7, #1 // CDEF_HAVE_LEFT
|
||||
b.eq 2f
|
||||
// CDEF_HAVE_LEFT
|
||||
sub \s1, \s1, #2
|
||||
sub \s2, \s2, #2
|
||||
tst w7, #2 // CDEF_HAVE_RIGHT
|
||||
b.eq 1f
|
||||
// CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
ldr \rn\()0, [\s1]
|
||||
ldr s1, [\s1, #\w]
|
||||
ldr \rn\()2, [\s2]
|
||||
ldr s3, [\s2, #\w]
|
||||
uxtl v0.8h, v0.8b
|
||||
uxtl v1.8h, v1.8b
|
||||
uxtl v2.8h, v2.8b
|
||||
uxtl v3.8h, v3.8b
|
||||
str \rw\()0, [x0]
|
||||
str d1, [x0, #2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
str \rw\()2, [x0]
|
||||
str d3, [x0, #2*\w]
|
||||
.if \ret
|
||||
ret
|
||||
.else
|
||||
add x0, x0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
1:
|
||||
// CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
ldr \rn\()0, [\s1]
|
||||
ldr h1, [\s1, #\w]
|
||||
ldr \rn\()2, [\s2]
|
||||
ldr h3, [\s2, #\w]
|
||||
uxtl v0.8h, v0.8b
|
||||
uxtl v1.8h, v1.8b
|
||||
uxtl v2.8h, v2.8b
|
||||
uxtl v3.8h, v3.8b
|
||||
str \rw\()0, [x0]
|
||||
str s1, [x0, #2*\w]
|
||||
str s31, [x0, #2*\w+4]
|
||||
add x0, x0, #2*\stride
|
||||
str \rw\()2, [x0]
|
||||
str s3, [x0, #2*\w]
|
||||
str s31, [x0, #2*\w+4]
|
||||
.if \ret
|
||||
ret
|
||||
.else
|
||||
add x0, x0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
2:
|
||||
// !CDEF_HAVE_LEFT
|
||||
tst w7, #2 // CDEF_HAVE_RIGHT
|
||||
b.eq 1f
|
||||
// !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
ldr \rn\()0, [\s1]
|
||||
ldr h1, [\s1, #\w]
|
||||
ldr \rn\()2, [\s2]
|
||||
ldr h3, [\s2, #\w]
|
||||
uxtl v0.8h, v0.8b
|
||||
uxtl v1.8h, v1.8b
|
||||
uxtl v2.8h, v2.8b
|
||||
uxtl v3.8h, v3.8b
|
||||
str s31, [x0]
|
||||
stur \rw\()0, [x0, #4]
|
||||
str s1, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
str s31, [x0]
|
||||
stur \rw\()2, [x0, #4]
|
||||
str s3, [x0, #4+2*\w]
|
||||
.if \ret
|
||||
ret
|
||||
.else
|
||||
add x0, x0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
1:
|
||||
// !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
ldr \rn\()0, [\s1]
|
||||
ldr \rn\()1, [\s2]
|
||||
uxtl v0.8h, v0.8b
|
||||
uxtl v1.8h, v1.8b
|
||||
str s31, [x0]
|
||||
stur \rw\()0, [x0, #4]
|
||||
str s31, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
str s31, [x0]
|
||||
stur \rw\()1, [x0, #4]
|
||||
str s31, [x0, #4+2*\w]
|
||||
.if \ret
|
||||
ret
|
||||
.else
|
||||
add x0, x0, #2*\stride
|
||||
.endif
|
||||
3:
|
||||
.endm
|
||||
|
||||
.macro load_n_incr dst, src, incr, w
|
||||
.if \w == 4
|
||||
ld1 {\dst\().s}[0], [\src], \incr
|
||||
.else
|
||||
ld1 {\dst\().8b}, [\src], \incr
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// void dav1d_cdef_paddingX_8bpc_neon(uint16_t *tmp, const pixel *src,
|
||||
// ptrdiff_t src_stride, const pixel (*left)[2],
|
||||
// const pixel *const top,
|
||||
// const pixel *const bottom, int h,
|
||||
// enum CdefEdgeFlags edges);
|
||||
|
||||
.macro padding_func w, stride, rn, rw
|
||||
function cdef_padding\w\()_8bpc_neon, export=1
|
||||
cmp w7, #0xf // fully edged
|
||||
b.eq cdef_padding\w\()_edged_8bpc_neon
|
||||
movi v30.8h, #0x80, lsl #8
|
||||
mov v31.16b, v30.16b
|
||||
sub x0, x0, #2*(2*\stride+2)
|
||||
tst w7, #4 // CDEF_HAVE_TOP
|
||||
b.ne 1f
|
||||
// !CDEF_HAVE_TOP
|
||||
st1 {v30.8h, v31.8h}, [x0], #32
|
||||
.if \w == 8
|
||||
st1 {v30.8h, v31.8h}, [x0], #32
|
||||
.endif
|
||||
b 3f
|
||||
1:
|
||||
// CDEF_HAVE_TOP
|
||||
add x9, x4, x2
|
||||
pad_top_bottom x4, x9, \w, \stride, \rn, \rw, 0
|
||||
|
||||
// Middle section
|
||||
3:
|
||||
tst w7, #1 // CDEF_HAVE_LEFT
|
||||
b.eq 2f
|
||||
// CDEF_HAVE_LEFT
|
||||
tst w7, #2 // CDEF_HAVE_RIGHT
|
||||
b.eq 1f
|
||||
// CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
0:
|
||||
ld1 {v0.h}[0], [x3], #2
|
||||
ldr h2, [x1, #\w]
|
||||
load_n_incr v1, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
uxtl v0.8h, v0.8b
|
||||
uxtl v1.8h, v1.8b
|
||||
uxtl v2.8h, v2.8b
|
||||
str s0, [x0]
|
||||
stur \rw\()1, [x0, #4]
|
||||
str s2, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
b.gt 0b
|
||||
b 3f
|
||||
1:
|
||||
// CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
ld1 {v0.h}[0], [x3], #2
|
||||
load_n_incr v1, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
uxtl v0.8h, v0.8b
|
||||
uxtl v1.8h, v1.8b
|
||||
str s0, [x0]
|
||||
stur \rw\()1, [x0, #4]
|
||||
str s31, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
b.gt 1b
|
||||
b 3f
|
||||
2:
|
||||
tst w7, #2 // CDEF_HAVE_RIGHT
|
||||
b.eq 1f
|
||||
// !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
0:
|
||||
ldr h1, [x1, #\w]
|
||||
load_n_incr v0, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
uxtl v0.8h, v0.8b
|
||||
uxtl v1.8h, v1.8b
|
||||
str s31, [x0]
|
||||
stur \rw\()0, [x0, #4]
|
||||
str s1, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
b.gt 0b
|
||||
b 3f
|
||||
1:
|
||||
// !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
load_n_incr v0, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
uxtl v0.8h, v0.8b
|
||||
str s31, [x0]
|
||||
stur \rw\()0, [x0, #4]
|
||||
str s31, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
b.gt 1b
|
||||
|
||||
3:
|
||||
tst w7, #8 // CDEF_HAVE_BOTTOM
|
||||
b.ne 1f
|
||||
// !CDEF_HAVE_BOTTOM
|
||||
st1 {v30.8h, v31.8h}, [x0], #32
|
||||
.if \w == 8
|
||||
st1 {v30.8h, v31.8h}, [x0], #32
|
||||
.endif
|
||||
ret
|
||||
1:
|
||||
// CDEF_HAVE_BOTTOM
|
||||
add x9, x5, x2
|
||||
pad_top_bottom x5, x9, \w, \stride, \rn, \rw, 1
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
padding_func 8, 16, d, q
|
||||
padding_func 4, 8, s, d
|
||||
|
||||
// void cdef_paddingX_edged_8bpc_neon(uint8_t *tmp, const pixel *src,
|
||||
// ptrdiff_t src_stride, const pixel (*left)[2],
|
||||
// const pixel *const top,
|
||||
// const pixel *const bottom, int h,
|
||||
// enum CdefEdgeFlags edges);
|
||||
|
||||
.macro padding_func_edged w, stride, reg
|
||||
function cdef_padding\w\()_edged_8bpc_neon, export=1
|
||||
sub x4, x4, #2
|
||||
sub x5, x5, #2
|
||||
sub x0, x0, #(2*\stride+2)
|
||||
|
||||
.if \w == 4
|
||||
ldr d0, [x4]
|
||||
ldr d1, [x4, x2]
|
||||
st1 {v0.8b, v1.8b}, [x0], #16
|
||||
.else
|
||||
add x9, x4, x2
|
||||
ldr d0, [x4]
|
||||
ldr s1, [x4, #8]
|
||||
ldr d2, [x9]
|
||||
ldr s3, [x9, #8]
|
||||
str d0, [x0]
|
||||
str s1, [x0, #8]
|
||||
str d2, [x0, #\stride]
|
||||
str s3, [x0, #\stride+8]
|
||||
add x0, x0, #2*\stride
|
||||
.endif
|
||||
|
||||
0:
|
||||
ld1 {v0.h}[0], [x3], #2
|
||||
ldr h2, [x1, #\w]
|
||||
load_n_incr v1, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
str h0, [x0]
|
||||
stur \reg\()1, [x0, #2]
|
||||
str h2, [x0, #2+\w]
|
||||
add x0, x0, #\stride
|
||||
b.gt 0b
|
||||
|
||||
.if \w == 4
|
||||
ldr d0, [x5]
|
||||
ldr d1, [x5, x2]
|
||||
st1 {v0.8b, v1.8b}, [x0], #16
|
||||
.else
|
||||
add x9, x5, x2
|
||||
ldr d0, [x5]
|
||||
ldr s1, [x5, #8]
|
||||
ldr d2, [x9]
|
||||
ldr s3, [x9, #8]
|
||||
str d0, [x0]
|
||||
str s1, [x0, #8]
|
||||
str d2, [x0, #\stride]
|
||||
str s3, [x0, #\stride+8]
|
||||
.endif
|
||||
ret
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
padding_func_edged 8, 16, d
|
||||
padding_func_edged 4, 8, s
|
||||
|
||||
tables
|
||||
|
||||
filter 8, 8
|
||||
filter 4, 8
|
||||
|
||||
find_dir 8
|
||||
|
||||
.macro load_px_8 d1, d2, w
|
||||
.if \w == 8
|
||||
add x6, x2, w9, sxtb // x + off
|
||||
sub x9, x2, w9, sxtb // x - off
|
||||
ld1 {\d1\().d}[0], [x6] // p0
|
||||
add x6, x6, #16 // += stride
|
||||
ld1 {\d2\().d}[0], [x9] // p1
|
||||
add x9, x9, #16 // += stride
|
||||
ld1 {\d1\().d}[1], [x6] // p0
|
||||
ld1 {\d2\().d}[1], [x9] // p0
|
||||
.else
|
||||
add x6, x2, w9, sxtb // x + off
|
||||
sub x9, x2, w9, sxtb // x - off
|
||||
ld1 {\d1\().s}[0], [x6] // p0
|
||||
add x6, x6, #8 // += stride
|
||||
ld1 {\d2\().s}[0], [x9] // p1
|
||||
add x9, x9, #8 // += stride
|
||||
ld1 {\d1\().s}[1], [x6] // p0
|
||||
add x6, x6, #8 // += stride
|
||||
ld1 {\d2\().s}[1], [x9] // p1
|
||||
add x9, x9, #8 // += stride
|
||||
ld1 {\d1\().s}[2], [x6] // p0
|
||||
add x6, x6, #8 // += stride
|
||||
ld1 {\d2\().s}[2], [x9] // p1
|
||||
add x9, x9, #8 // += stride
|
||||
ld1 {\d1\().s}[3], [x6] // p0
|
||||
ld1 {\d2\().s}[3], [x9] // p1
|
||||
.endif
|
||||
.endm
|
||||
.macro handle_pixel_8 s1, s2, thresh_vec, shift, tap, min
|
||||
.if \min
|
||||
umin v3.16b, v3.16b, \s1\().16b
|
||||
umax v4.16b, v4.16b, \s1\().16b
|
||||
umin v3.16b, v3.16b, \s2\().16b
|
||||
umax v4.16b, v4.16b, \s2\().16b
|
||||
.endif
|
||||
uabd v16.16b, v0.16b, \s1\().16b // abs(diff)
|
||||
uabd v20.16b, v0.16b, \s2\().16b // abs(diff)
|
||||
ushl v17.16b, v16.16b, \shift // abs(diff) >> shift
|
||||
ushl v21.16b, v20.16b, \shift // abs(diff) >> shift
|
||||
uqsub v17.16b, \thresh_vec, v17.16b // clip = imax(0, threshold - (abs(diff) >> shift))
|
||||
uqsub v21.16b, \thresh_vec, v21.16b // clip = imax(0, threshold - (abs(diff) >> shift))
|
||||
cmhi v18.16b, v0.16b, \s1\().16b // px > p0
|
||||
cmhi v22.16b, v0.16b, \s2\().16b // px > p1
|
||||
umin v17.16b, v17.16b, v16.16b // imin(abs(diff), clip)
|
||||
umin v21.16b, v21.16b, v20.16b // imin(abs(diff), clip)
|
||||
dup v19.16b, \tap // taps[k]
|
||||
neg v16.16b, v17.16b // -imin()
|
||||
neg v20.16b, v21.16b // -imin()
|
||||
bsl v18.16b, v16.16b, v17.16b // constrain() = apply_sign()
|
||||
bsl v22.16b, v20.16b, v21.16b // constrain() = apply_sign()
|
||||
mla v1.16b, v18.16b, v19.16b // sum += taps[k] * constrain()
|
||||
mla v2.16b, v22.16b, v19.16b // sum += taps[k] * constrain()
|
||||
.endm
|
||||
|
||||
// void cdef_filterX_edged_8bpc_neon(pixel *dst, ptrdiff_t dst_stride,
|
||||
// const uint8_t *tmp, int pri_strength,
|
||||
// int sec_strength, int dir, int damping,
|
||||
// int h);
|
||||
.macro filter_func_8 w, pri, sec, min, suffix
|
||||
function cdef_filter\w\suffix\()_edged_8bpc_neon
|
||||
.if \pri
|
||||
movrel x8, pri_taps
|
||||
and w9, w3, #1
|
||||
add x8, x8, w9, uxtw #1
|
||||
.endif
|
||||
movrel x9, directions\w
|
||||
add x5, x9, w5, uxtw #1
|
||||
movi v30.8b, #7
|
||||
dup v28.8b, w6 // damping
|
||||
|
||||
.if \pri
|
||||
dup v25.16b, w3 // threshold
|
||||
.endif
|
||||
.if \sec
|
||||
dup v27.16b, w4 // threshold
|
||||
.endif
|
||||
trn1 v24.8b, v25.8b, v27.8b
|
||||
clz v24.8b, v24.8b // clz(threshold)
|
||||
sub v24.8b, v30.8b, v24.8b // ulog2(threshold)
|
||||
uqsub v24.8b, v28.8b, v24.8b // shift = imax(0, damping - ulog2(threshold))
|
||||
neg v24.8b, v24.8b // -shift
|
||||
.if \sec
|
||||
dup v26.16b, v24.b[1]
|
||||
.endif
|
||||
.if \pri
|
||||
dup v24.16b, v24.b[0]
|
||||
.endif
|
||||
|
||||
1:
|
||||
.if \w == 8
|
||||
add x12, x2, #16
|
||||
ld1 {v0.d}[0], [x2] // px
|
||||
ld1 {v0.d}[1], [x12] // px
|
||||
.else
|
||||
add x12, x2, #1*8
|
||||
add x13, x2, #2*8
|
||||
add x14, x2, #3*8
|
||||
ld1 {v0.s}[0], [x2] // px
|
||||
ld1 {v0.s}[1], [x12] // px
|
||||
ld1 {v0.s}[2], [x13] // px
|
||||
ld1 {v0.s}[3], [x14] // px
|
||||
.endif
|
||||
|
||||
// We need 9-bits or two 8-bit accululators to fit the sum.
|
||||
// Max of |sum| > 15*2*6(pri) + 4*4*3(sec) = 228.
|
||||
// Start sum at -1 instead of 0 to help handle rounding later.
|
||||
movi v1.16b, #255 // sum
|
||||
movi v2.16b, #0 // sum
|
||||
.if \min
|
||||
mov v3.16b, v0.16b // min
|
||||
mov v4.16b, v0.16b // max
|
||||
.endif
|
||||
|
||||
// Instead of loading sec_taps 2, 1 from memory, just set it
|
||||
// to 2 initially and decrease for the second round.
|
||||
// This is also used as loop counter.
|
||||
mov w11, #2 // sec_taps[0]
|
||||
|
||||
2:
|
||||
.if \pri
|
||||
ldrb w9, [x5] // off1
|
||||
|
||||
load_px_8 v5, v6, \w
|
||||
.endif
|
||||
|
||||
.if \sec
|
||||
add x5, x5, #4 // +2*2
|
||||
ldrb w9, [x5] // off2
|
||||
load_px_8 v28, v29, \w
|
||||
.endif
|
||||
|
||||
.if \pri
|
||||
ldrb w10, [x8] // *pri_taps
|
||||
|
||||
handle_pixel_8 v5, v6, v25.16b, v24.16b, w10, \min
|
||||
.endif
|
||||
|
||||
.if \sec
|
||||
add x5, x5, #8 // +2*4
|
||||
ldrb w9, [x5] // off3
|
||||
load_px_8 v5, v6, \w
|
||||
|
||||
handle_pixel_8 v28, v29, v27.16b, v26.16b, w11, \min
|
||||
|
||||
handle_pixel_8 v5, v6, v27.16b, v26.16b, w11, \min
|
||||
|
||||
sub x5, x5, #11 // x5 -= 2*(2+4); x5 += 1;
|
||||
.else
|
||||
add x5, x5, #1 // x5 += 1
|
||||
.endif
|
||||
subs w11, w11, #1 // sec_tap-- (value)
|
||||
.if \pri
|
||||
add x8, x8, #1 // pri_taps++ (pointer)
|
||||
.endif
|
||||
b.ne 2b
|
||||
|
||||
// Perform halving adds since the value won't fit otherwise.
|
||||
// To handle the offset for negative values, use both halving w/ and w/o rounding.
|
||||
srhadd v5.16b, v1.16b, v2.16b // sum >> 1
|
||||
shadd v6.16b, v1.16b, v2.16b // (sum - 1) >> 1
|
||||
cmlt v1.16b, v5.16b, #0 // sum < 0
|
||||
bsl v1.16b, v6.16b, v5.16b // (sum - (sum < 0)) >> 1
|
||||
|
||||
srshr v1.16b, v1.16b, #3 // (8 + sum - (sum < 0)) >> 4
|
||||
|
||||
usqadd v0.16b, v1.16b // px + (8 + sum ...) >> 4
|
||||
.if \min
|
||||
umin v0.16b, v0.16b, v4.16b
|
||||
umax v0.16b, v0.16b, v3.16b // iclip(px + .., min, max)
|
||||
.endif
|
||||
.if \w == 8
|
||||
st1 {v0.d}[0], [x0], x1
|
||||
add x2, x2, #2*16 // tmp += 2*tmp_stride
|
||||
subs w7, w7, #2 // h -= 2
|
||||
st1 {v0.d}[1], [x0], x1
|
||||
.else
|
||||
st1 {v0.s}[0], [x0], x1
|
||||
add x2, x2, #4*8 // tmp += 4*tmp_stride
|
||||
st1 {v0.s}[1], [x0], x1
|
||||
subs w7, w7, #4 // h -= 4
|
||||
st1 {v0.s}[2], [x0], x1
|
||||
st1 {v0.s}[3], [x0], x1
|
||||
.endif
|
||||
|
||||
// Reset pri_taps and directions back to the original point
|
||||
sub x5, x5, #2
|
||||
.if \pri
|
||||
sub x8, x8, #2
|
||||
.endif
|
||||
|
||||
b.gt 1b
|
||||
ret
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
.macro filter_8 w
|
||||
filter_func_8 \w, pri=1, sec=0, min=0, suffix=_pri
|
||||
filter_func_8 \w, pri=0, sec=1, min=0, suffix=_sec
|
||||
filter_func_8 \w, pri=1, sec=1, min=1, suffix=_pri_sec
|
||||
.endm
|
||||
|
||||
filter_8 8
|
||||
filter_8 4
|
||||
229
media/libdav1d/src/src/arm/64/cdef16.S
Normal file
229
media/libdav1d/src/src/arm/64/cdef16.S
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2020, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
#include "cdef_tmpl.S"
|
||||
|
||||
.macro pad_top_bot_16 s1, s2, w, stride, reg, ret
|
||||
tst w7, #1 // CDEF_HAVE_LEFT
|
||||
b.eq 2f
|
||||
// CDEF_HAVE_LEFT
|
||||
sub \s1, \s1, #4
|
||||
sub \s2, \s2, #4
|
||||
tst w7, #2 // CDEF_HAVE_RIGHT
|
||||
b.eq 1f
|
||||
// CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
ldr \reg\()0, [\s1]
|
||||
ldr d1, [\s1, #2*\w]
|
||||
ldr \reg\()2, [\s2]
|
||||
ldr d3, [\s2, #2*\w]
|
||||
str \reg\()0, [x0]
|
||||
str d1, [x0, #2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
str \reg\()2, [x0]
|
||||
str d3, [x0, #2*\w]
|
||||
.if \ret
|
||||
ret
|
||||
.else
|
||||
add x0, x0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
1:
|
||||
// CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
ldr \reg\()0, [\s1]
|
||||
ldr s1, [\s1, #2*\w]
|
||||
ldr \reg\()2, [\s2]
|
||||
ldr s3, [\s2, #2*\w]
|
||||
str \reg\()0, [x0]
|
||||
str s1, [x0, #2*\w]
|
||||
str s31, [x0, #2*\w+4]
|
||||
add x0, x0, #2*\stride
|
||||
str \reg\()2, [x0]
|
||||
str s3, [x0, #2*\w]
|
||||
str s31, [x0, #2*\w+4]
|
||||
.if \ret
|
||||
ret
|
||||
.else
|
||||
add x0, x0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
2:
|
||||
// !CDEF_HAVE_LEFT
|
||||
tst w7, #2 // CDEF_HAVE_RIGHT
|
||||
b.eq 1f
|
||||
// !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
ldr \reg\()0, [\s1]
|
||||
ldr s1, [\s1, #2*\w]
|
||||
ldr \reg\()2, [\s2]
|
||||
ldr s3, [\s2, #2*\w]
|
||||
str s31, [x0]
|
||||
stur \reg\()0, [x0, #4]
|
||||
str s1, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
str s31, [x0]
|
||||
stur \reg\()2, [x0, #4]
|
||||
str s3, [x0, #4+2*\w]
|
||||
.if \ret
|
||||
ret
|
||||
.else
|
||||
add x0, x0, #2*\stride
|
||||
b 3f
|
||||
.endif
|
||||
|
||||
1:
|
||||
// !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
ldr \reg\()0, [\s1]
|
||||
ldr \reg\()1, [\s2]
|
||||
str s31, [x0]
|
||||
stur \reg\()0, [x0, #4]
|
||||
str s31, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
str s31, [x0]
|
||||
stur \reg\()1, [x0, #4]
|
||||
str s31, [x0, #4+2*\w]
|
||||
.if \ret
|
||||
ret
|
||||
.else
|
||||
add x0, x0, #2*\stride
|
||||
.endif
|
||||
3:
|
||||
.endm
|
||||
|
||||
.macro load_n_incr_16 dst, src, incr, w
|
||||
.if \w == 4
|
||||
ld1 {\dst\().4h}, [\src], \incr
|
||||
.else
|
||||
ld1 {\dst\().8h}, [\src], \incr
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// void dav1d_cdef_paddingX_16bpc_neon(uint16_t *tmp, const pixel *src,
|
||||
// ptrdiff_t src_stride, const pixel (*left)[2],
|
||||
// const pixel *const top,
|
||||
// const pixel *const bottom, int h,
|
||||
// enum CdefEdgeFlags edges);
|
||||
|
||||
.macro padding_func_16 w, stride, reg
|
||||
function cdef_padding\w\()_16bpc_neon, export=1
|
||||
movi v30.8h, #0x80, lsl #8
|
||||
mov v31.16b, v30.16b
|
||||
sub x0, x0, #2*(2*\stride+2)
|
||||
tst w7, #4 // CDEF_HAVE_TOP
|
||||
b.ne 1f
|
||||
// !CDEF_HAVE_TOP
|
||||
st1 {v30.8h, v31.8h}, [x0], #32
|
||||
.if \w == 8
|
||||
st1 {v30.8h, v31.8h}, [x0], #32
|
||||
.endif
|
||||
b 3f
|
||||
1:
|
||||
// CDEF_HAVE_TOP
|
||||
add x9, x4, x2
|
||||
pad_top_bot_16 x4, x9, \w, \stride, \reg, 0
|
||||
|
||||
// Middle section
|
||||
3:
|
||||
tst w7, #1 // CDEF_HAVE_LEFT
|
||||
b.eq 2f
|
||||
// CDEF_HAVE_LEFT
|
||||
tst w7, #2 // CDEF_HAVE_RIGHT
|
||||
b.eq 1f
|
||||
// CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
0:
|
||||
ld1 {v0.s}[0], [x3], #4
|
||||
ldr s2, [x1, #2*\w]
|
||||
load_n_incr_16 v1, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
str s0, [x0]
|
||||
stur \reg\()1, [x0, #4]
|
||||
str s2, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
b.gt 0b
|
||||
b 3f
|
||||
1:
|
||||
// CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
ld1 {v0.s}[0], [x3], #4
|
||||
load_n_incr_16 v1, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
str s0, [x0]
|
||||
stur \reg\()1, [x0, #4]
|
||||
str s31, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
b.gt 1b
|
||||
b 3f
|
||||
2:
|
||||
tst w7, #2 // CDEF_HAVE_RIGHT
|
||||
b.eq 1f
|
||||
// !CDEF_HAVE_LEFT+CDEF_HAVE_RIGHT
|
||||
0:
|
||||
ldr s1, [x1, #2*\w]
|
||||
load_n_incr_16 v0, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
str s31, [x0]
|
||||
stur \reg\()0, [x0, #4]
|
||||
str s1, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
b.gt 0b
|
||||
b 3f
|
||||
1:
|
||||
// !CDEF_HAVE_LEFT+!CDEF_HAVE_RIGHT
|
||||
load_n_incr_16 v0, x1, x2, \w
|
||||
subs w6, w6, #1
|
||||
str s31, [x0]
|
||||
stur \reg\()0, [x0, #4]
|
||||
str s31, [x0, #4+2*\w]
|
||||
add x0, x0, #2*\stride
|
||||
b.gt 1b
|
||||
|
||||
3:
|
||||
tst w7, #8 // CDEF_HAVE_BOTTOM
|
||||
b.ne 1f
|
||||
// !CDEF_HAVE_BOTTOM
|
||||
st1 {v30.8h, v31.8h}, [x0], #32
|
||||
.if \w == 8
|
||||
st1 {v30.8h, v31.8h}, [x0], #32
|
||||
.endif
|
||||
ret
|
||||
1:
|
||||
// CDEF_HAVE_BOTTOM
|
||||
add x9, x5, x2
|
||||
pad_top_bot_16 x5, x9, \w, \stride, \reg, 1
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
padding_func_16 8, 16, q
|
||||
padding_func_16 4, 8, d
|
||||
|
||||
tables
|
||||
|
||||
filter 8, 16
|
||||
filter 4, 16
|
||||
|
||||
find_dir 16
|
||||
511
media/libdav1d/src/src/arm/64/cdef_tmpl.S
Normal file
511
media/libdav1d/src/src/arm/64/cdef_tmpl.S
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2020, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
.macro dir_table w, stride
|
||||
const directions\w
|
||||
.byte -1 * \stride + 1, -2 * \stride + 2
|
||||
.byte 0 * \stride + 1, -1 * \stride + 2
|
||||
.byte 0 * \stride + 1, 0 * \stride + 2
|
||||
.byte 0 * \stride + 1, 1 * \stride + 2
|
||||
.byte 1 * \stride + 1, 2 * \stride + 2
|
||||
.byte 1 * \stride + 0, 2 * \stride + 1
|
||||
.byte 1 * \stride + 0, 2 * \stride + 0
|
||||
.byte 1 * \stride + 0, 2 * \stride - 1
|
||||
// Repeated, to avoid & 7
|
||||
.byte -1 * \stride + 1, -2 * \stride + 2
|
||||
.byte 0 * \stride + 1, -1 * \stride + 2
|
||||
.byte 0 * \stride + 1, 0 * \stride + 2
|
||||
.byte 0 * \stride + 1, 1 * \stride + 2
|
||||
.byte 1 * \stride + 1, 2 * \stride + 2
|
||||
.byte 1 * \stride + 0, 2 * \stride + 1
|
||||
endconst
|
||||
.endm
|
||||
|
||||
.macro tables
|
||||
dir_table 8, 16
|
||||
dir_table 4, 8
|
||||
|
||||
const pri_taps
|
||||
.byte 4, 2, 3, 3
|
||||
endconst
|
||||
.endm
|
||||
|
||||
.macro load_px d1, d2, w
|
||||
.if \w == 8
|
||||
add x6, x2, w9, sxtb #1 // x + off
|
||||
sub x9, x2, w9, sxtb #1 // x - off
|
||||
ld1 {\d1\().8h}, [x6] // p0
|
||||
ld1 {\d2\().8h}, [x9] // p1
|
||||
.else
|
||||
add x6, x2, w9, sxtb #1 // x + off
|
||||
sub x9, x2, w9, sxtb #1 // x - off
|
||||
ld1 {\d1\().4h}, [x6] // p0
|
||||
add x6, x6, #2*8 // += stride
|
||||
ld1 {\d2\().4h}, [x9] // p1
|
||||
add x9, x9, #2*8 // += stride
|
||||
ld1 {\d1\().d}[1], [x6] // p0
|
||||
ld1 {\d2\().d}[1], [x9] // p1
|
||||
.endif
|
||||
.endm
|
||||
.macro handle_pixel s1, s2, thresh_vec, shift, tap, min
|
||||
.if \min
|
||||
umin v2.8h, v2.8h, \s1\().8h
|
||||
smax v3.8h, v3.8h, \s1\().8h
|
||||
umin v2.8h, v2.8h, \s2\().8h
|
||||
smax v3.8h, v3.8h, \s2\().8h
|
||||
.endif
|
||||
uabd v16.8h, v0.8h, \s1\().8h // abs(diff)
|
||||
uabd v20.8h, v0.8h, \s2\().8h // abs(diff)
|
||||
ushl v17.8h, v16.8h, \shift // abs(diff) >> shift
|
||||
ushl v21.8h, v20.8h, \shift // abs(diff) >> shift
|
||||
uqsub v17.8h, \thresh_vec, v17.8h // clip = imax(0, threshold - (abs(diff) >> shift))
|
||||
uqsub v21.8h, \thresh_vec, v21.8h // clip = imax(0, threshold - (abs(diff) >> shift))
|
||||
sub v18.8h, \s1\().8h, v0.8h // diff = p0 - px
|
||||
sub v22.8h, \s2\().8h, v0.8h // diff = p1 - px
|
||||
neg v16.8h, v17.8h // -clip
|
||||
neg v20.8h, v21.8h // -clip
|
||||
smin v18.8h, v18.8h, v17.8h // imin(diff, clip)
|
||||
smin v22.8h, v22.8h, v21.8h // imin(diff, clip)
|
||||
dup v19.8h, \tap // taps[k]
|
||||
smax v18.8h, v18.8h, v16.8h // constrain() = imax(imin(diff, clip), -clip)
|
||||
smax v22.8h, v22.8h, v20.8h // constrain() = imax(imin(diff, clip), -clip)
|
||||
mla v1.8h, v18.8h, v19.8h // sum += taps[k] * constrain()
|
||||
mla v1.8h, v22.8h, v19.8h // sum += taps[k] * constrain()
|
||||
.endm
|
||||
|
||||
// void dav1d_cdef_filterX_Ybpc_neon(pixel *dst, ptrdiff_t dst_stride,
|
||||
// const uint16_t *tmp, int pri_strength,
|
||||
// int sec_strength, int dir, int damping,
|
||||
// int h, size_t edges);
|
||||
.macro filter_func w, bpc, pri, sec, min, suffix
|
||||
function cdef_filter\w\suffix\()_\bpc\()bpc_neon
|
||||
.if \bpc == 8
|
||||
ldr w8, [sp] // edges
|
||||
cmp w8, #0xf
|
||||
b.eq cdef_filter\w\suffix\()_edged_8bpc_neon
|
||||
.endif
|
||||
.if \pri
|
||||
.if \bpc == 16
|
||||
ldr w9, [sp, #8] // bitdepth_max
|
||||
clz w9, w9
|
||||
sub w9, w9, #24 // -bitdepth_min_8
|
||||
neg w9, w9 // bitdepth_min_8
|
||||
.endif
|
||||
movrel x8, pri_taps
|
||||
.if \bpc == 16
|
||||
lsr w9, w3, w9 // pri_strength >> bitdepth_min_8
|
||||
and w9, w9, #1 // (pri_strength >> bitdepth_min_8) & 1
|
||||
.else
|
||||
and w9, w3, #1
|
||||
.endif
|
||||
add x8, x8, w9, uxtw #1
|
||||
.endif
|
||||
movrel x9, directions\w
|
||||
add x5, x9, w5, uxtw #1
|
||||
movi v30.4h, #15
|
||||
dup v28.4h, w6 // damping
|
||||
|
||||
.if \pri
|
||||
dup v25.8h, w3 // threshold
|
||||
.endif
|
||||
.if \sec
|
||||
dup v27.8h, w4 // threshold
|
||||
.endif
|
||||
trn1 v24.4h, v25.4h, v27.4h
|
||||
clz v24.4h, v24.4h // clz(threshold)
|
||||
sub v24.4h, v30.4h, v24.4h // ulog2(threshold)
|
||||
uqsub v24.4h, v28.4h, v24.4h // shift = imax(0, damping - ulog2(threshold))
|
||||
neg v24.4h, v24.4h // -shift
|
||||
.if \sec
|
||||
dup v26.8h, v24.h[1]
|
||||
.endif
|
||||
.if \pri
|
||||
dup v24.8h, v24.h[0]
|
||||
.endif
|
||||
|
||||
1:
|
||||
.if \w == 8
|
||||
ld1 {v0.8h}, [x2] // px
|
||||
.else
|
||||
add x12, x2, #2*8
|
||||
ld1 {v0.4h}, [x2] // px
|
||||
ld1 {v0.d}[1], [x12] // px
|
||||
.endif
|
||||
|
||||
movi v1.8h, #0 // sum
|
||||
.if \min
|
||||
mov v2.16b, v0.16b // min
|
||||
mov v3.16b, v0.16b // max
|
||||
.endif
|
||||
|
||||
// Instead of loading sec_taps 2, 1 from memory, just set it
|
||||
// to 2 initially and decrease for the second round.
|
||||
// This is also used as loop counter.
|
||||
mov w11, #2 // sec_taps[0]
|
||||
|
||||
2:
|
||||
.if \pri
|
||||
ldrb w9, [x5] // off1
|
||||
|
||||
load_px v4, v5, \w
|
||||
.endif
|
||||
|
||||
.if \sec
|
||||
add x5, x5, #4 // +2*2
|
||||
ldrb w9, [x5] // off2
|
||||
load_px v6, v7, \w
|
||||
.endif
|
||||
|
||||
.if \pri
|
||||
ldrb w10, [x8] // *pri_taps
|
||||
|
||||
handle_pixel v4, v5, v25.8h, v24.8h, w10, \min
|
||||
.endif
|
||||
|
||||
.if \sec
|
||||
add x5, x5, #8 // +2*4
|
||||
ldrb w9, [x5] // off3
|
||||
load_px v4, v5, \w
|
||||
|
||||
handle_pixel v6, v7, v27.8h, v26.8h, w11, \min
|
||||
|
||||
handle_pixel v4, v5, v27.8h, v26.8h, w11, \min
|
||||
|
||||
sub x5, x5, #11 // x5 -= 2*(2+4); x5 += 1;
|
||||
.else
|
||||
add x5, x5, #1 // x5 += 1
|
||||
.endif
|
||||
subs w11, w11, #1 // sec_tap-- (value)
|
||||
.if \pri
|
||||
add x8, x8, #1 // pri_taps++ (pointer)
|
||||
.endif
|
||||
b.ne 2b
|
||||
|
||||
cmlt v4.8h, v1.8h, #0 // -(sum < 0)
|
||||
add v1.8h, v1.8h, v4.8h // sum - (sum < 0)
|
||||
srshr v1.8h, v1.8h, #4 // (8 + sum - (sum < 0)) >> 4
|
||||
add v0.8h, v0.8h, v1.8h // px + (8 + sum ...) >> 4
|
||||
.if \min
|
||||
smin v0.8h, v0.8h, v3.8h
|
||||
smax v0.8h, v0.8h, v2.8h // iclip(px + .., min, max)
|
||||
.endif
|
||||
.if \bpc == 8
|
||||
xtn v0.8b, v0.8h
|
||||
.endif
|
||||
.if \w == 8
|
||||
add x2, x2, #2*16 // tmp += tmp_stride
|
||||
subs w7, w7, #1 // h--
|
||||
.if \bpc == 8
|
||||
st1 {v0.8b}, [x0], x1
|
||||
.else
|
||||
st1 {v0.8h}, [x0], x1
|
||||
.endif
|
||||
.else
|
||||
.if \bpc == 8
|
||||
st1 {v0.s}[0], [x0], x1
|
||||
.else
|
||||
st1 {v0.d}[0], [x0], x1
|
||||
.endif
|
||||
add x2, x2, #2*16 // tmp += 2*tmp_stride
|
||||
subs w7, w7, #2 // h -= 2
|
||||
.if \bpc == 8
|
||||
st1 {v0.s}[1], [x0], x1
|
||||
.else
|
||||
st1 {v0.d}[1], [x0], x1
|
||||
.endif
|
||||
.endif
|
||||
|
||||
// Reset pri_taps and directions back to the original point
|
||||
sub x5, x5, #2
|
||||
.if \pri
|
||||
sub x8, x8, #2
|
||||
.endif
|
||||
|
||||
b.gt 1b
|
||||
ret
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
.macro filter w, bpc
|
||||
filter_func \w, \bpc, pri=1, sec=0, min=0, suffix=_pri
|
||||
filter_func \w, \bpc, pri=0, sec=1, min=0, suffix=_sec
|
||||
filter_func \w, \bpc, pri=1, sec=1, min=1, suffix=_pri_sec
|
||||
|
||||
function cdef_filter\w\()_\bpc\()bpc_neon, export=1
|
||||
cbnz w3, 1f // pri_strength
|
||||
b cdef_filter\w\()_sec_\bpc\()bpc_neon // only sec
|
||||
1:
|
||||
cbnz w4, 1f // sec_strength
|
||||
b cdef_filter\w\()_pri_\bpc\()bpc_neon // only pri
|
||||
1:
|
||||
b cdef_filter\w\()_pri_sec_\bpc\()bpc_neon // both pri and sec
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
const div_table
|
||||
.short 840, 420, 280, 210, 168, 140, 120, 105
|
||||
endconst
|
||||
|
||||
const alt_fact
|
||||
.short 420, 210, 140, 105, 105, 105, 105, 105, 140, 210, 420, 0
|
||||
endconst
|
||||
|
||||
.macro cost_alt d1, d2, s1, s2, s3, s4
|
||||
smull v22.4s, \s1\().4h, \s1\().4h // sum_alt[n]*sum_alt[n]
|
||||
smull2 v23.4s, \s1\().8h, \s1\().8h
|
||||
smull v24.4s, \s2\().4h, \s2\().4h
|
||||
smull v25.4s, \s3\().4h, \s3\().4h // sum_alt[n]*sum_alt[n]
|
||||
smull2 v26.4s, \s3\().8h, \s3\().8h
|
||||
smull v27.4s, \s4\().4h, \s4\().4h
|
||||
mul v22.4s, v22.4s, v29.4s // sum_alt[n]^2*fact
|
||||
mla v22.4s, v23.4s, v30.4s
|
||||
mla v22.4s, v24.4s, v31.4s
|
||||
mul v25.4s, v25.4s, v29.4s // sum_alt[n]^2*fact
|
||||
mla v25.4s, v26.4s, v30.4s
|
||||
mla v25.4s, v27.4s, v31.4s
|
||||
addv \d1, v22.4s // *cost_ptr
|
||||
addv \d2, v25.4s // *cost_ptr
|
||||
.endm
|
||||
|
||||
.macro find_best s1, s2, s3
|
||||
.ifnb \s2
|
||||
mov w5, \s2\().s[0]
|
||||
.endif
|
||||
cmp w4, w1 // cost[n] > best_cost
|
||||
csel w0, w3, w0, gt // best_dir = n
|
||||
csel w1, w4, w1, gt // best_cost = cost[n]
|
||||
.ifnb \s2
|
||||
add w3, w3, #1 // n++
|
||||
cmp w5, w1 // cost[n] > best_cost
|
||||
mov w4, \s3\().s[0]
|
||||
csel w0, w3, w0, gt // best_dir = n
|
||||
csel w1, w5, w1, gt // best_cost = cost[n]
|
||||
add w3, w3, #1 // n++
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// Steps for loading and preparing each row
|
||||
.macro dir_load_step1 s1, bpc
|
||||
.if \bpc == 8
|
||||
ld1 {\s1\().8b}, [x0], x1
|
||||
.else
|
||||
ld1 {\s1\().8h}, [x0], x1
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro dir_load_step2 s1, bpc
|
||||
.if \bpc == 8
|
||||
usubl \s1\().8h, \s1\().8b, v31.8b
|
||||
.else
|
||||
ushl \s1\().8h, \s1\().8h, v8.8h
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro dir_load_step3 s1, bpc
|
||||
// Nothing for \bpc == 8
|
||||
.if \bpc != 8
|
||||
sub \s1\().8h, \s1\().8h, v31.8h
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// int dav1d_cdef_find_dir_Xbpc_neon(const pixel *img, const ptrdiff_t stride,
|
||||
// unsigned *const var)
|
||||
.macro find_dir bpc
|
||||
function cdef_find_dir_\bpc\()bpc_neon, export=1
|
||||
.if \bpc == 16
|
||||
str d8, [sp, #-0x10]!
|
||||
clz w3, w3 // clz(bitdepth_max)
|
||||
sub w3, w3, #24 // -bitdepth_min_8
|
||||
dup v8.8h, w3
|
||||
.endif
|
||||
sub sp, sp, #32 // cost
|
||||
mov w3, #8
|
||||
.if \bpc == 8
|
||||
movi v31.16b, #128
|
||||
.else
|
||||
movi v31.8h, #128
|
||||
.endif
|
||||
movi v30.16b, #0
|
||||
movi v1.8h, #0 // v0-v1 sum_diag[0]
|
||||
movi v3.8h, #0 // v2-v3 sum_diag[1]
|
||||
movi v5.8h, #0 // v4-v5 sum_hv[0-1]
|
||||
movi v7.8h, #0 // v6-v7 sum_alt[0]
|
||||
dir_load_step1 v26, \bpc // Setup first row early
|
||||
movi v17.8h, #0 // v16-v17 sum_alt[1]
|
||||
movi v18.8h, #0 // v18-v19 sum_alt[2]
|
||||
dir_load_step2 v26, \bpc
|
||||
movi v19.8h, #0
|
||||
dir_load_step3 v26, \bpc
|
||||
movi v21.8h, #0 // v20-v21 sum_alt[3]
|
||||
|
||||
.irpc i, 01234567
|
||||
addv h25, v26.8h // [y]
|
||||
rev64 v27.8h, v26.8h
|
||||
addp v28.8h, v26.8h, v30.8h // [(x >> 1)]
|
||||
add v5.8h, v5.8h, v26.8h // sum_hv[1]
|
||||
ext v27.16b, v27.16b, v27.16b, #8 // [-x]
|
||||
rev64 v29.4h, v28.4h // [-(x >> 1)]
|
||||
ins v4.h[\i], v25.h[0] // sum_hv[0]
|
||||
.if \i < 6
|
||||
ext v22.16b, v30.16b, v26.16b, #(16-2*(3-(\i/2)))
|
||||
ext v23.16b, v26.16b, v30.16b, #(16-2*(3-(\i/2)))
|
||||
add v18.8h, v18.8h, v22.8h // sum_alt[2]
|
||||
add v19.4h, v19.4h, v23.4h // sum_alt[2]
|
||||
.else
|
||||
add v18.8h, v18.8h, v26.8h // sum_alt[2]
|
||||
.endif
|
||||
.if \i == 0
|
||||
mov v20.16b, v26.16b // sum_alt[3]
|
||||
.elseif \i == 1
|
||||
add v20.8h, v20.8h, v26.8h // sum_alt[3]
|
||||
.else
|
||||
ext v24.16b, v30.16b, v26.16b, #(16-2*(\i/2))
|
||||
ext v25.16b, v26.16b, v30.16b, #(16-2*(\i/2))
|
||||
add v20.8h, v20.8h, v24.8h // sum_alt[3]
|
||||
add v21.4h, v21.4h, v25.4h // sum_alt[3]
|
||||
.endif
|
||||
.if \i == 0
|
||||
mov v0.16b, v26.16b // sum_diag[0]
|
||||
dir_load_step1 v26, \bpc
|
||||
mov v2.16b, v27.16b // sum_diag[1]
|
||||
dir_load_step2 v26, \bpc
|
||||
mov v6.16b, v28.16b // sum_alt[0]
|
||||
dir_load_step3 v26, \bpc
|
||||
mov v16.16b, v29.16b // sum_alt[1]
|
||||
.else
|
||||
ext v22.16b, v30.16b, v26.16b, #(16-2*\i)
|
||||
ext v23.16b, v26.16b, v30.16b, #(16-2*\i)
|
||||
ext v24.16b, v30.16b, v27.16b, #(16-2*\i)
|
||||
ext v25.16b, v27.16b, v30.16b, #(16-2*\i)
|
||||
.if \i != 7 // Nothing to load for the final row
|
||||
dir_load_step1 v26, \bpc // Start setting up the next row early.
|
||||
.endif
|
||||
add v0.8h, v0.8h, v22.8h // sum_diag[0]
|
||||
add v1.8h, v1.8h, v23.8h // sum_diag[0]
|
||||
add v2.8h, v2.8h, v24.8h // sum_diag[1]
|
||||
add v3.8h, v3.8h, v25.8h // sum_diag[1]
|
||||
.if \i != 7
|
||||
dir_load_step2 v26, \bpc
|
||||
.endif
|
||||
ext v22.16b, v30.16b, v28.16b, #(16-2*\i)
|
||||
ext v23.16b, v28.16b, v30.16b, #(16-2*\i)
|
||||
ext v24.16b, v30.16b, v29.16b, #(16-2*\i)
|
||||
ext v25.16b, v29.16b, v30.16b, #(16-2*\i)
|
||||
.if \i != 7
|
||||
dir_load_step3 v26, \bpc
|
||||
.endif
|
||||
add v6.8h, v6.8h, v22.8h // sum_alt[0]
|
||||
add v7.4h, v7.4h, v23.4h // sum_alt[0]
|
||||
add v16.8h, v16.8h, v24.8h // sum_alt[1]
|
||||
add v17.4h, v17.4h, v25.4h // sum_alt[1]
|
||||
.endif
|
||||
.endr
|
||||
|
||||
movi v31.4s, #105
|
||||
|
||||
smull v26.4s, v4.4h, v4.4h // sum_hv[0]*sum_hv[0]
|
||||
smlal2 v26.4s, v4.8h, v4.8h
|
||||
smull v27.4s, v5.4h, v5.4h // sum_hv[1]*sum_hv[1]
|
||||
smlal2 v27.4s, v5.8h, v5.8h
|
||||
mul v26.4s, v26.4s, v31.4s // cost[2] *= 105
|
||||
mul v27.4s, v27.4s, v31.4s // cost[6] *= 105
|
||||
addv s4, v26.4s // cost[2]
|
||||
addv s5, v27.4s // cost[6]
|
||||
|
||||
rev64 v1.8h, v1.8h
|
||||
rev64 v3.8h, v3.8h
|
||||
ext v1.16b, v1.16b, v1.16b, #10 // sum_diag[0][14-n]
|
||||
ext v3.16b, v3.16b, v3.16b, #10 // sum_diag[1][14-n]
|
||||
|
||||
str s4, [sp, #2*4] // cost[2]
|
||||
str s5, [sp, #6*4] // cost[6]
|
||||
|
||||
movrel x4, div_table
|
||||
ld1 {v31.8h}, [x4]
|
||||
|
||||
smull v22.4s, v0.4h, v0.4h // sum_diag[0]*sum_diag[0]
|
||||
smull2 v23.4s, v0.8h, v0.8h
|
||||
smlal v22.4s, v1.4h, v1.4h
|
||||
smlal2 v23.4s, v1.8h, v1.8h
|
||||
smull v24.4s, v2.4h, v2.4h // sum_diag[1]*sum_diag[1]
|
||||
smull2 v25.4s, v2.8h, v2.8h
|
||||
smlal v24.4s, v3.4h, v3.4h
|
||||
smlal2 v25.4s, v3.8h, v3.8h
|
||||
uxtl v30.4s, v31.4h // div_table
|
||||
uxtl2 v31.4s, v31.8h
|
||||
mul v22.4s, v22.4s, v30.4s // cost[0]
|
||||
mla v22.4s, v23.4s, v31.4s // cost[0]
|
||||
mul v24.4s, v24.4s, v30.4s // cost[4]
|
||||
mla v24.4s, v25.4s, v31.4s // cost[4]
|
||||
addv s0, v22.4s // cost[0]
|
||||
addv s2, v24.4s // cost[4]
|
||||
|
||||
movrel x5, alt_fact
|
||||
ld1 {v29.4h, v30.4h, v31.4h}, [x5]// div_table[2*m+1] + 105
|
||||
|
||||
str s0, [sp, #0*4] // cost[0]
|
||||
str s2, [sp, #4*4] // cost[4]
|
||||
|
||||
uxtl v29.4s, v29.4h // div_table[2*m+1] + 105
|
||||
uxtl v30.4s, v30.4h
|
||||
uxtl v31.4s, v31.4h
|
||||
|
||||
cost_alt s6, s16, v6, v7, v16, v17 // cost[1], cost[3]
|
||||
cost_alt s18, s20, v18, v19, v20, v21 // cost[5], cost[7]
|
||||
str s6, [sp, #1*4] // cost[1]
|
||||
str s16, [sp, #3*4] // cost[3]
|
||||
|
||||
mov w0, #0 // best_dir
|
||||
mov w1, v0.s[0] // best_cost
|
||||
mov w3, #1 // n
|
||||
|
||||
str s18, [sp, #5*4] // cost[5]
|
||||
str s20, [sp, #7*4] // cost[7]
|
||||
|
||||
mov w4, v6.s[0]
|
||||
|
||||
find_best v6, v4, v16
|
||||
find_best v16, v2, v18
|
||||
find_best v18, v5, v20
|
||||
find_best v20
|
||||
|
||||
eor w3, w0, #4 // best_dir ^4
|
||||
ldr w4, [sp, w3, uxtw #2]
|
||||
sub w1, w1, w4 // best_cost - cost[best_dir ^ 4]
|
||||
lsr w1, w1, #10
|
||||
str w1, [x2] // *var
|
||||
|
||||
add sp, sp, #32
|
||||
.if \bpc == 16
|
||||
ldr d8, [sp], 0x10
|
||||
.endif
|
||||
ret
|
||||
endfunc
|
||||
.endm
|
||||
2015
media/libdav1d/src/src/arm/64/filmgrain.S
Normal file
2015
media/libdav1d/src/src/arm/64/filmgrain.S
Normal file
File diff suppressed because it is too large
Load diff
2002
media/libdav1d/src/src/arm/64/filmgrain16.S
Normal file
2002
media/libdav1d/src/src/arm/64/filmgrain16.S
Normal file
File diff suppressed because it is too large
Load diff
5342
media/libdav1d/src/src/arm/64/ipred.S
Normal file
5342
media/libdav1d/src/src/arm/64/ipred.S
Normal file
File diff suppressed because it is too large
Load diff
5714
media/libdav1d/src/src/arm/64/ipred16.S
Normal file
5714
media/libdav1d/src/src/arm/64/ipred16.S
Normal file
File diff suppressed because it is too large
Load diff
3270
media/libdav1d/src/src/arm/64/itx.S
Normal file
3270
media/libdav1d/src/src/arm/64/itx.S
Normal file
File diff suppressed because it is too large
Load diff
3657
media/libdav1d/src/src/arm/64/itx16.S
Normal file
3657
media/libdav1d/src/src/arm/64/itx16.S
Normal file
File diff suppressed because it is too large
Load diff
1129
media/libdav1d/src/src/arm/64/loopfilter.S
Normal file
1129
media/libdav1d/src/src/arm/64/loopfilter.S
Normal file
File diff suppressed because it is too large
Load diff
925
media/libdav1d/src/src/arm/64/loopfilter16.S
Normal file
925
media/libdav1d/src/src/arm/64/loopfilter16.S
Normal file
|
|
@ -0,0 +1,925 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2020, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
// depending on how many pixels need to be stored, returns:
|
||||
// x14 = (1 << 0) : 0 pixels
|
||||
// x14 = (1 << 4) : inner 4 pixels
|
||||
// x14 = (1 << 6) : inner 6 pixels
|
||||
// x14 = 0 : all pixels
|
||||
.macro loop_filter wd
|
||||
function lpf_8_wd\wd\()_neon
|
||||
uabd v0.8h, v22.8h, v23.8h // abs(p1 - p0)
|
||||
uabd v1.8h, v25.8h, v24.8h // abs(q1 - q0)
|
||||
uabd v2.8h, v23.8h, v24.8h // abs(p0 - q0)
|
||||
uabd v3.8h, v22.8h, v25.8h // abs(p1 - q1)
|
||||
.if \wd >= 6
|
||||
uabd v4.8h, v21.8h, v22.8h // abs(p2 - p1)
|
||||
uabd v5.8h, v26.8h, v25.8h // abs(q2 - q1)
|
||||
.endif
|
||||
.if \wd >= 8
|
||||
uabd v6.8h, v20.8h, v21.8h // abs(p3 - p2)
|
||||
uabd v7.8h, v27.8h, v26.8h // abs(q3 - q3)
|
||||
.endif
|
||||
.if \wd >= 6
|
||||
umax v4.8h, v4.8h, v5.8h
|
||||
.endif
|
||||
uqadd v2.8h, v2.8h, v2.8h // abs(p0 - q0) * 2
|
||||
.if \wd >= 8
|
||||
umax v6.8h, v6.8h, v7.8h
|
||||
.endif
|
||||
ushr v3.8h, v3.8h, #1
|
||||
.if \wd >= 8
|
||||
umax v4.8h, v4.8h, v6.8h
|
||||
.endif
|
||||
.if \wd >= 6
|
||||
and v4.16b, v4.16b, v14.16b
|
||||
.endif
|
||||
umax v0.8h, v0.8h, v1.8h // max(abs(p1 - p0), abs(q1 - q0))
|
||||
uqadd v2.8h, v2.8h, v3.8h // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1
|
||||
.if \wd >= 6
|
||||
umax v4.8h, v0.8h, v4.8h
|
||||
cmhs v1.8h, v11.8h, v4.8h // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I
|
||||
.else
|
||||
cmhs v1.8h, v11.8h, v0.8h // max(abs(p1 - p0), abs(q1 - q0)) <= I
|
||||
.endif
|
||||
cmhs v2.8h, v10.8h, v2.8h // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E
|
||||
and v1.16b, v1.16b, v2.16b // fm
|
||||
and v1.16b, v1.16b, v13.16b // fm && wd >= 4
|
||||
.if \wd >= 6
|
||||
and v14.16b, v14.16b, v1.16b // fm && wd > 4
|
||||
.endif
|
||||
.if \wd >= 16
|
||||
and v15.16b, v15.16b, v1.16b // fm && wd == 16
|
||||
.endif
|
||||
|
||||
mov x16, v1.d[0]
|
||||
mov x17, v1.d[1]
|
||||
adds x16, x16, x17
|
||||
b.ne 9f // if (!fm || wd < 4) return;
|
||||
mov x14, #(1 << 0)
|
||||
ret
|
||||
9:
|
||||
.if \wd >= 6
|
||||
movi v10.8h, #1
|
||||
uabd v2.8h, v21.8h, v23.8h // abs(p2 - p0)
|
||||
uabd v3.8h, v22.8h, v23.8h // abs(p1 - p0)
|
||||
uabd v4.8h, v25.8h, v24.8h // abs(q1 - q0)
|
||||
uabd v5.8h, v26.8h, v24.8h // abs(q2 - q0)
|
||||
dup v9.8h, w9 // bitdepth_min_8
|
||||
.if \wd >= 8
|
||||
uabd v6.8h, v20.8h, v23.8h // abs(p3 - p0)
|
||||
uabd v7.8h, v27.8h, v24.8h // abs(q3 - q0)
|
||||
.endif
|
||||
umax v2.8h, v2.8h, v3.8h
|
||||
umax v4.8h, v4.8h, v5.8h
|
||||
.if \wd >= 8
|
||||
umax v6.8h, v6.8h, v7.8h
|
||||
.endif
|
||||
umax v2.8h, v2.8h, v4.8h
|
||||
ushl v10.8h, v10.8h, v9.8h // F = 1 << bitdepth_min_8
|
||||
.if \wd >= 8
|
||||
umax v2.8h, v2.8h, v6.8h
|
||||
.endif
|
||||
|
||||
.if \wd == 16
|
||||
uabd v3.8h, v17.8h, v23.8h // abs(p6 - p0)
|
||||
uabd v4.8h, v18.8h, v23.8h // abs(p5 - p0)
|
||||
uabd v5.8h, v19.8h, v23.8h // abs(p4 - p0)
|
||||
.endif
|
||||
cmhs v2.8h, v10.8h, v2.8h // flat8in
|
||||
.if \wd == 16
|
||||
uabd v6.8h, v28.8h, v24.8h // abs(q4 - q0)
|
||||
uabd v7.8h, v29.8h, v24.8h // abs(q5 - q0)
|
||||
uabd v8.8h, v30.8h, v24.8h // abs(q6 - q0)
|
||||
.endif
|
||||
and v14.16b, v2.16b, v14.16b // flat8in && fm && wd > 4
|
||||
bic v1.16b, v1.16b, v14.16b // fm && wd >= 4 && !flat8in
|
||||
.if \wd == 16
|
||||
umax v3.8h, v3.8h, v4.8h
|
||||
umax v5.8h, v5.8h, v6.8h
|
||||
.endif
|
||||
mov x16, v1.d[0]
|
||||
mov x17, v1.d[1]
|
||||
.if \wd == 16
|
||||
umax v7.8h, v7.8h, v8.8h
|
||||
umax v3.8h, v3.8h, v5.8h
|
||||
umax v3.8h, v3.8h, v7.8h
|
||||
cmhs v3.8h, v10.8h, v3.8h // flat8out
|
||||
.endif
|
||||
adds x16, x16, x17
|
||||
.if \wd == 16
|
||||
and v15.16b, v15.16b, v3.16b // flat8out && fm && wd == 16
|
||||
and v15.16b, v15.16b, v14.16b // flat8out && flat8in && fm && wd == 16
|
||||
bic v14.16b, v14.16b, v15.16b // flat8in && fm && wd >= 4 && !flat8out
|
||||
.endif
|
||||
b.eq 1f // skip wd == 4 case
|
||||
.endif
|
||||
|
||||
dup v3.8h, w8 // bitdepth_max
|
||||
sub v2.8h, v22.8h, v25.8h // p1 - q1
|
||||
ushr v3.8h, v3.8h, #1 // 128 << bitdepth_min_8 - 1
|
||||
cmhi v0.8h, v0.8h, v12.8h // hev
|
||||
not v9.16b, v3.16b // - 128 * (1 << bitdepth_min_8)
|
||||
smin v2.8h, v2.8h, v3.8h // iclip_diff(p1 - q1)
|
||||
smax v2.8h, v2.8h, v9.8h // iclip_diff(p1 - q1)
|
||||
and v4.16b, v2.16b, v0.16b // if (hev) iclip_diff(p1 - q1)
|
||||
sub v2.8h, v24.8h, v23.8h
|
||||
movi v5.8h, #3
|
||||
bic v0.16b, v1.16b, v0.16b // (fm && wd >= 4 && !hev)
|
||||
mul v2.8h, v2.8h, v5.8h
|
||||
movi v6.8h, #4
|
||||
add v2.8h, v2.8h, v4.8h
|
||||
smin v2.8h, v2.8h, v3.8h // f = iclip_diff()
|
||||
smax v2.8h, v2.8h, v9.8h // f = iclip_diff()
|
||||
sqadd v4.8h, v6.8h, v2.8h // f + 4
|
||||
sqadd v5.8h, v5.8h, v2.8h // f + 3
|
||||
smin v4.8h, v4.8h, v3.8h // imin(f + 4, 128 << bitdepth_min_8 - 1)
|
||||
smin v5.8h, v5.8h, v3.8h // imin(f + 3, 128 << bitdepth_min_8 - 1)
|
||||
sshr v4.8h, v4.8h, #3 // f1
|
||||
sshr v5.8h, v5.8h, #3 // f2
|
||||
movi v9.8h, #0
|
||||
dup v3.8h, w8 // bitdepth_max
|
||||
sqadd v2.8h, v23.8h, v5.8h // p0 + f2
|
||||
sqsub v6.8h, v24.8h, v4.8h // q0 - f1
|
||||
srshr v4.8h, v4.8h, #1 // (f1 + 1) >> 1
|
||||
smin v2.8h, v2.8h, v3.8h // out p0 = iclip_pixel()
|
||||
smin v6.8h, v6.8h, v3.8h // out q0 = iclip_pixel()
|
||||
smax v2.8h, v2.8h, v9.8h // out p0 = iclip_pixel()
|
||||
smax v6.8h, v6.8h, v9.8h // out q0 = iclip_pixel()
|
||||
bit v23.16b, v2.16b, v1.16b // if (fm && wd >= 4)
|
||||
bit v24.16b, v6.16b, v1.16b // if (fm && wd >= 4)
|
||||
sqadd v2.8h, v22.8h, v4.8h // p1 + f
|
||||
sqsub v6.8h, v25.8h, v4.8h // q1 - f
|
||||
smin v2.8h, v2.8h, v3.8h // out p1 = iclip_pixel()
|
||||
smin v6.8h, v6.8h, v3.8h // out q1 = iclip_pixel()
|
||||
smax v2.8h, v2.8h, v9.8h // out p1 = iclip_pixel()
|
||||
smax v6.8h, v6.8h, v9.8h // out q1 = iclip_pixel()
|
||||
bit v22.16b, v2.16b, v0.16b // if (fm && wd >= 4 && !hev)
|
||||
bit v25.16b, v6.16b, v0.16b // if (fm && wd >= 4 && !hev)
|
||||
1:
|
||||
|
||||
.if \wd == 6
|
||||
mov x16, v14.d[0]
|
||||
mov x17, v14.d[1]
|
||||
adds x16, x16, x17
|
||||
b.eq 2f // skip if there's no flat8in
|
||||
|
||||
add v0.8h, v21.8h, v21.8h // p2 * 2
|
||||
add v2.8h, v21.8h, v22.8h // p2 + p1
|
||||
add v4.8h, v22.8h, v23.8h // p1 + p0
|
||||
add v6.8h, v23.8h, v24.8h // p0 + q0
|
||||
add v8.8h, v0.8h, v2.8h
|
||||
add v10.8h, v4.8h, v6.8h
|
||||
add v12.8h, v24.8h, v25.8h // q0 + q1
|
||||
add v8.8h, v8.8h, v10.8h
|
||||
sub v12.8h, v12.8h, v0.8h
|
||||
add v10.8h, v25.8h, v26.8h // q1 + q2
|
||||
urshr v0.8h, v8.8h, #3 // out p1
|
||||
|
||||
add v8.8h, v8.8h, v12.8h
|
||||
sub v10.8h, v10.8h, v2.8h
|
||||
add v12.8h, v26.8h, v26.8h // q2 + q2
|
||||
urshr v1.8h, v8.8h, #3 // out p0
|
||||
|
||||
add v8.8h, v8.8h, v10.8h
|
||||
sub v12.8h, v12.8h, v4.8h
|
||||
urshr v2.8h, v8.8h, #3 // out q0
|
||||
|
||||
bit v22.16b, v0.16b, v14.16b // p1 if (flat8in)
|
||||
add v8.8h, v8.8h, v12.8h
|
||||
bit v23.16b, v1.16b, v14.16b // p0 if (flat8in)
|
||||
urshr v3.8h, v8.8h, #3 // out q1
|
||||
bit v24.16b, v2.16b, v14.16b // q0 if (flat8in)
|
||||
bit v25.16b, v3.16b, v14.16b // q1 if (flat8in)
|
||||
.elseif \wd >= 8
|
||||
mov x16, v14.d[0]
|
||||
mov x17, v14.d[1]
|
||||
adds x16, x16, x17
|
||||
.if \wd == 8
|
||||
b.eq 8f // skip if there's no flat8in
|
||||
.else
|
||||
b.eq 2f // skip if there's no flat8in
|
||||
.endif
|
||||
|
||||
add v0.8h, v20.8h, v21.8h // p3 + p2
|
||||
add v2.8h, v22.8h, v25.8h // p1 + q1
|
||||
add v4.8h, v20.8h, v22.8h // p3 + p1
|
||||
add v6.8h, v23.8h, v26.8h // p0 + q2
|
||||
add v8.8h, v0.8h, v0.8h // 2 * (p3 + p2)
|
||||
add v9.8h, v23.8h, v24.8h // p0 + q0
|
||||
add v8.8h, v8.8h, v4.8h // + p3 + p1
|
||||
sub v2.8h, v2.8h, v0.8h // p1 + q1 - p3 - p2
|
||||
add v8.8h, v8.8h, v9.8h // + p0 + q0
|
||||
sub v6.8h, v6.8h, v4.8h // p0 + q2 - p3 - p1
|
||||
urshr v10.8h, v8.8h, #3 // out p2
|
||||
|
||||
add v8.8h, v8.8h, v2.8h
|
||||
add v0.8h, v20.8h, v23.8h // p3 + p0
|
||||
add v2.8h, v24.8h, v27.8h // q0 + q3
|
||||
urshr v11.8h, v8.8h, #3 // out p1
|
||||
|
||||
add v8.8h, v8.8h, v6.8h
|
||||
sub v2.8h, v2.8h, v0.8h // q0 + q3 - p3 - p0
|
||||
add v4.8h, v21.8h, v24.8h // p2 + q0
|
||||
add v6.8h, v25.8h, v27.8h // q1 + q3
|
||||
urshr v12.8h, v8.8h, #3 // out p0
|
||||
|
||||
add v8.8h, v8.8h, v2.8h
|
||||
sub v6.8h, v6.8h, v4.8h // q1 + q3 - p2 - q0
|
||||
add v0.8h, v22.8h, v25.8h // p1 + q1
|
||||
add v2.8h, v26.8h, v27.8h // q2 + q3
|
||||
urshr v13.8h, v8.8h, #3 // out q0
|
||||
|
||||
add v8.8h, v8.8h, v6.8h
|
||||
sub v2.8h, v2.8h, v0.8h // q2 + q3 - p1 - q1
|
||||
urshr v0.8h, v8.8h, #3 // out q1
|
||||
|
||||
add v8.8h, v8.8h, v2.8h
|
||||
|
||||
bit v21.16b, v10.16b, v14.16b
|
||||
bit v22.16b, v11.16b, v14.16b
|
||||
bit v23.16b, v12.16b, v14.16b
|
||||
urshr v1.8h, v8.8h, #3 // out q2
|
||||
bit v24.16b, v13.16b, v14.16b
|
||||
bit v25.16b, v0.16b, v14.16b
|
||||
bit v26.16b, v1.16b, v14.16b
|
||||
.endif
|
||||
2:
|
||||
.if \wd == 16
|
||||
mov x16, v15.d[0]
|
||||
mov x17, v15.d[1]
|
||||
adds x16, x16, x17
|
||||
b.ne 1f // check if flat8out is needed
|
||||
mov x16, v14.d[0]
|
||||
mov x17, v14.d[1]
|
||||
adds x16, x16, x17
|
||||
b.eq 8f // if there was no flat8in, just write the inner 4 pixels
|
||||
b 7f // if flat8in was used, write the inner 6 pixels
|
||||
1:
|
||||
|
||||
add v2.8h, v17.8h, v17.8h // p6 + p6
|
||||
add v4.8h, v17.8h, v18.8h // p6 + p5
|
||||
add v6.8h, v17.8h, v19.8h // p6 + p4
|
||||
add v8.8h, v17.8h, v20.8h // p6 + p3
|
||||
add v12.8h, v2.8h, v4.8h
|
||||
add v10.8h, v6.8h, v8.8h
|
||||
add v6.8h, v17.8h, v21.8h // p6 + p2
|
||||
add v12.8h, v12.8h, v10.8h
|
||||
add v8.8h, v17.8h, v22.8h // p6 + p1
|
||||
add v10.8h, v18.8h, v23.8h // p5 + p0
|
||||
add v6.8h, v6.8h, v8.8h
|
||||
add v8.8h, v19.8h, v24.8h // p4 + q0
|
||||
add v12.8h, v12.8h, v6.8h
|
||||
add v10.8h, v10.8h, v8.8h
|
||||
add v6.8h, v20.8h, v25.8h // p3 + q1
|
||||
add v12.8h, v12.8h, v10.8h
|
||||
sub v6.8h, v6.8h, v2.8h
|
||||
add v2.8h, v21.8h, v26.8h // p2 + q2
|
||||
urshr v0.8h, v12.8h, #4 // out p5
|
||||
add v12.8h, v12.8h, v6.8h // - (p6 + p6) + (p3 + q1)
|
||||
sub v2.8h, v2.8h, v4.8h
|
||||
add v4.8h, v22.8h, v27.8h // p1 + q3
|
||||
add v6.8h, v17.8h, v19.8h // p6 + p4
|
||||
urshr v1.8h, v12.8h, #4 // out p4
|
||||
add v12.8h, v12.8h, v2.8h // - (p6 + p5) + (p2 + q2)
|
||||
sub v4.8h, v4.8h, v6.8h
|
||||
add v6.8h, v23.8h, v28.8h // p0 + q4
|
||||
add v8.8h, v17.8h, v20.8h // p6 + p3
|
||||
urshr v2.8h, v12.8h, #4 // out p3
|
||||
add v12.8h, v12.8h, v4.8h // - (p6 + p4) + (p1 + q3)
|
||||
sub v6.8h, v6.8h, v8.8h
|
||||
add v8.8h, v24.8h, v29.8h // q0 + q5
|
||||
add v4.8h, v17.8h, v21.8h // p6 + p2
|
||||
urshr v3.8h, v12.8h, #4 // out p2
|
||||
add v12.8h, v12.8h, v6.8h // - (p6 + p3) + (p0 + q4)
|
||||
sub v8.8h, v8.8h, v4.8h
|
||||
add v6.8h, v25.8h, v30.8h // q1 + q6
|
||||
add v10.8h, v17.8h, v22.8h // p6 + p1
|
||||
urshr v4.8h, v12.8h, #4 // out p1
|
||||
add v12.8h, v12.8h, v8.8h // - (p6 + p2) + (q0 + q5)
|
||||
sub v6.8h, v6.8h, v10.8h
|
||||
add v8.8h, v26.8h, v30.8h // q2 + q6
|
||||
bif v0.16b, v18.16b, v15.16b // out p5
|
||||
add v10.8h, v18.8h, v23.8h // p5 + p0
|
||||
urshr v5.8h, v12.8h, #4 // out p0
|
||||
add v12.8h, v12.8h, v6.8h // - (p6 + p1) + (q1 + q6)
|
||||
sub v8.8h, v8.8h, v10.8h
|
||||
add v10.8h, v27.8h, v30.8h // q3 + q6
|
||||
bif v1.16b, v19.16b, v15.16b // out p4
|
||||
add v18.8h, v19.8h, v24.8h // p4 + q0
|
||||
urshr v6.8h, v12.8h, #4 // out q0
|
||||
add v12.8h, v12.8h, v8.8h // - (p5 + p0) + (q2 + q6)
|
||||
sub v10.8h, v10.8h, v18.8h
|
||||
add v8.8h, v28.8h, v30.8h // q4 + q6
|
||||
bif v2.16b, v20.16b, v15.16b // out p3
|
||||
add v18.8h, v20.8h, v25.8h // p3 + q1
|
||||
urshr v7.8h, v12.8h, #4 // out q1
|
||||
add v12.8h, v12.8h, v10.8h // - (p4 + q0) + (q3 + q6)
|
||||
sub v18.8h, v8.8h, v18.8h
|
||||
add v10.8h, v29.8h, v30.8h // q5 + q6
|
||||
bif v3.16b, v21.16b, v15.16b // out p2
|
||||
add v20.8h, v21.8h, v26.8h // p2 + q2
|
||||
urshr v8.8h, v12.8h, #4 // out q2
|
||||
add v12.8h, v12.8h, v18.8h // - (p3 + q1) + (q4 + q6)
|
||||
sub v10.8h, v10.8h, v20.8h
|
||||
add v18.8h, v30.8h, v30.8h // q6 + q6
|
||||
bif v4.16b, v22.16b, v15.16b // out p1
|
||||
add v20.8h, v22.8h, v27.8h // p1 + q3
|
||||
urshr v9.8h, v12.8h, #4 // out q3
|
||||
add v12.8h, v12.8h, v10.8h // - (p2 + q2) + (q5 + q6)
|
||||
sub v18.8h, v18.8h, v20.8h
|
||||
bif v5.16b, v23.16b, v15.16b // out p0
|
||||
urshr v10.8h, v12.8h, #4 // out q4
|
||||
add v12.8h, v12.8h, v18.8h // - (p1 + q3) + (q6 + q6)
|
||||
urshr v11.8h, v12.8h, #4 // out q5
|
||||
bif v6.16b, v24.16b, v15.16b // out q0
|
||||
bif v7.16b, v25.16b, v15.16b // out q1
|
||||
bif v8.16b, v26.16b, v15.16b // out q2
|
||||
bif v9.16b, v27.16b, v15.16b // out q3
|
||||
bif v10.16b, v28.16b, v15.16b // out q4
|
||||
bif v11.16b, v29.16b, v15.16b // out q5
|
||||
.endif
|
||||
|
||||
mov x14, #0
|
||||
ret
|
||||
.if \wd == 16
|
||||
7:
|
||||
// Return to a shorter epilogue, writing only the inner 6 pixels
|
||||
mov x14, #(1 << 6)
|
||||
ret
|
||||
.endif
|
||||
.if \wd >= 8
|
||||
8:
|
||||
// Return to a shorter epilogue, writing only the inner 4 pixels
|
||||
mov x14, #(1 << 4)
|
||||
ret
|
||||
.endif
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
loop_filter 16
|
||||
loop_filter 8
|
||||
loop_filter 6
|
||||
loop_filter 4
|
||||
|
||||
.macro lpf_8_wd16
|
||||
bl lpf_8_wd16_neon
|
||||
cbz x14, 1f
|
||||
tbnz x14, #6, 7f
|
||||
tbnz x14, #4, 8f
|
||||
ret x15
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro lpf_8_wd8
|
||||
bl lpf_8_wd8_neon
|
||||
cbz x14, 1f
|
||||
tbnz x14, #4, 8f
|
||||
ret x15
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro lpf_8_wd6
|
||||
bl lpf_8_wd6_neon
|
||||
cbz x14, 1f
|
||||
ret x15
|
||||
1:
|
||||
.endm
|
||||
|
||||
.macro lpf_8_wd4
|
||||
bl lpf_8_wd4_neon
|
||||
cbz x14, 1f
|
||||
ret x15
|
||||
1:
|
||||
.endm
|
||||
|
||||
function lpf_v_4_8_neon
|
||||
mov x15, x30
|
||||
sub x16, x0, x1, lsl #1
|
||||
ld1 {v22.8h}, [x16], x1 // p1
|
||||
ld1 {v24.8h}, [x0], x1 // q0
|
||||
ld1 {v23.8h}, [x16], x1 // p0
|
||||
ld1 {v25.8h}, [x0], x1 // q1
|
||||
sub x0, x0, x1, lsl #1
|
||||
|
||||
lpf_8_wd4
|
||||
|
||||
sub x16, x0, x1, lsl #1
|
||||
st1 {v22.8h}, [x16], x1 // p1
|
||||
st1 {v24.8h}, [x0], x1 // q0
|
||||
st1 {v23.8h}, [x16], x1 // p0
|
||||
st1 {v25.8h}, [x0], x1 // q1
|
||||
sub x0, x0, x1, lsl #1
|
||||
ret x15
|
||||
endfunc
|
||||
|
||||
function lpf_h_4_8_neon
|
||||
mov x15, x30
|
||||
sub x16, x0, #4
|
||||
add x0, x16, x1, lsl #2
|
||||
ld1 {v22.d}[0], [x16], x1
|
||||
ld1 {v22.d}[1], [x0], x1
|
||||
ld1 {v23.d}[0], [x16], x1
|
||||
ld1 {v23.d}[1], [x0], x1
|
||||
ld1 {v24.d}[0], [x16], x1
|
||||
ld1 {v24.d}[1], [x0], x1
|
||||
ld1 {v25.d}[0], [x16], x1
|
||||
ld1 {v25.d}[1], [x0], x1
|
||||
add x0, x0, #4
|
||||
|
||||
transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29
|
||||
|
||||
lpf_8_wd4
|
||||
|
||||
sub x16, x0, x1, lsl #3
|
||||
sub x16, x16, #4
|
||||
transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29
|
||||
add x0, x16, x1, lsl #2
|
||||
|
||||
st1 {v22.d}[0], [x16], x1
|
||||
st1 {v22.d}[1], [x0], x1
|
||||
st1 {v23.d}[0], [x16], x1
|
||||
st1 {v23.d}[1], [x0], x1
|
||||
st1 {v24.d}[0], [x16], x1
|
||||
st1 {v24.d}[1], [x0], x1
|
||||
st1 {v25.d}[0], [x16], x1
|
||||
st1 {v25.d}[1], [x0], x1
|
||||
add x0, x0, #4
|
||||
ret x15
|
||||
endfunc
|
||||
|
||||
function lpf_v_6_8_neon
|
||||
mov x15, x30
|
||||
sub x16, x0, x1, lsl #1
|
||||
sub x16, x16, x1
|
||||
ld1 {v21.8h}, [x16], x1 // p2
|
||||
ld1 {v24.8h}, [x0], x1 // q0
|
||||
ld1 {v22.8h}, [x16], x1 // p1
|
||||
ld1 {v25.8h}, [x0], x1 // q1
|
||||
ld1 {v23.8h}, [x16], x1 // p0
|
||||
ld1 {v26.8h}, [x0], x1 // q2
|
||||
sub x0, x0, x1, lsl #1
|
||||
sub x0, x0, x1
|
||||
|
||||
lpf_8_wd6
|
||||
|
||||
sub x16, x0, x1, lsl #1
|
||||
st1 {v22.8h}, [x16], x1 // p1
|
||||
st1 {v24.8h}, [x0], x1 // q0
|
||||
st1 {v23.8h}, [x16], x1 // p0
|
||||
st1 {v25.8h}, [x0], x1 // q1
|
||||
sub x0, x0, x1, lsl #1
|
||||
ret x15
|
||||
endfunc
|
||||
|
||||
function lpf_h_6_8_neon
|
||||
mov x15, x30
|
||||
sub x16, x0, #8
|
||||
add x0, x16, x1, lsl #2
|
||||
ld1 {v20.8h}, [x16], x1
|
||||
ld1 {v24.8h}, [x0], x1
|
||||
ld1 {v21.8h}, [x16], x1
|
||||
ld1 {v25.8h}, [x0], x1
|
||||
ld1 {v22.8h}, [x16], x1
|
||||
ld1 {v26.8h}, [x0], x1
|
||||
ld1 {v23.8h}, [x16], x1
|
||||
ld1 {v27.8h}, [x0], x1
|
||||
add x0, x0, #8
|
||||
|
||||
transpose_8x8h v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
|
||||
|
||||
lpf_8_wd6
|
||||
|
||||
sub x16, x0, x1, lsl #3
|
||||
sub x16, x16, #4
|
||||
transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29
|
||||
add x0, x16, x1, lsl #2
|
||||
|
||||
st1 {v22.d}[0], [x16], x1
|
||||
st1 {v22.d}[1], [x0], x1
|
||||
st1 {v23.d}[0], [x16], x1
|
||||
st1 {v23.d}[1], [x0], x1
|
||||
st1 {v24.d}[0], [x16], x1
|
||||
st1 {v24.d}[1], [x0], x1
|
||||
st1 {v25.d}[0], [x16], x1
|
||||
st1 {v25.d}[1], [x0], x1
|
||||
add x0, x0, #4
|
||||
ret x15
|
||||
endfunc
|
||||
|
||||
function lpf_v_8_8_neon
|
||||
mov x15, x30
|
||||
sub x16, x0, x1, lsl #2
|
||||
ld1 {v20.8h}, [x16], x1 // p3
|
||||
ld1 {v24.8h}, [x0], x1 // q0
|
||||
ld1 {v21.8h}, [x16], x1 // p2
|
||||
ld1 {v25.8h}, [x0], x1 // q1
|
||||
ld1 {v22.8h}, [x16], x1 // p1
|
||||
ld1 {v26.8h}, [x0], x1 // q2
|
||||
ld1 {v23.8h}, [x16], x1 // p0
|
||||
ld1 {v27.8h}, [x0], x1 // q3
|
||||
sub x0, x0, x1, lsl #2
|
||||
|
||||
lpf_8_wd8
|
||||
|
||||
sub x16, x0, x1, lsl #1
|
||||
sub x16, x16, x1
|
||||
st1 {v21.8h}, [x16], x1 // p2
|
||||
st1 {v24.8h}, [x0], x1 // q0
|
||||
st1 {v22.8h}, [x16], x1 // p1
|
||||
st1 {v25.8h}, [x0], x1 // q1
|
||||
st1 {v23.8h}, [x16], x1 // p0
|
||||
st1 {v26.8h}, [x0], x1 // q2
|
||||
sub x0, x0, x1, lsl #1
|
||||
sub x0, x0, x1
|
||||
ret x15
|
||||
|
||||
8:
|
||||
sub x16, x0, x1, lsl #1
|
||||
st1 {v22.8h}, [x16], x1 // p1
|
||||
st1 {v24.8h}, [x0], x1 // q0
|
||||
st1 {v23.8h}, [x16], x1 // p0
|
||||
st1 {v25.8h}, [x0], x1 // q1
|
||||
sub x0, x0, x1, lsl #1
|
||||
ret x15
|
||||
endfunc
|
||||
|
||||
function lpf_h_8_8_neon
|
||||
mov x15, x30
|
||||
sub x16, x0, #8
|
||||
add x0, x16, x1, lsl #2
|
||||
ld1 {v20.8h}, [x16], x1
|
||||
ld1 {v24.8h}, [x0], x1
|
||||
ld1 {v21.8h}, [x16], x1
|
||||
ld1 {v25.8h}, [x0], x1
|
||||
ld1 {v22.8h}, [x16], x1
|
||||
ld1 {v26.8h}, [x0], x1
|
||||
ld1 {v23.8h}, [x16], x1
|
||||
ld1 {v27.8h}, [x0], x1
|
||||
add x0, x0, #8
|
||||
|
||||
transpose_8x8h v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
|
||||
|
||||
lpf_8_wd8
|
||||
|
||||
sub x16, x0, x1, lsl #3
|
||||
sub x16, x16, #8
|
||||
transpose_8x8h v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
|
||||
add x0, x16, x1, lsl #2
|
||||
|
||||
st1 {v20.8h}, [x16], x1
|
||||
st1 {v24.8h}, [x0], x1
|
||||
st1 {v21.8h}, [x16], x1
|
||||
st1 {v25.8h}, [x0], x1
|
||||
st1 {v22.8h}, [x16], x1
|
||||
st1 {v26.8h}, [x0], x1
|
||||
st1 {v23.8h}, [x16], x1
|
||||
st1 {v27.8h}, [x0], x1
|
||||
add x0, x0, #8
|
||||
ret x15
|
||||
8:
|
||||
sub x16, x0, x1, lsl #3
|
||||
sub x16, x16, #4
|
||||
transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29
|
||||
add x0, x16, x1, lsl #2
|
||||
|
||||
st1 {v22.d}[0], [x16], x1
|
||||
st1 {v22.d}[1], [x0], x1
|
||||
st1 {v23.d}[0], [x16], x1
|
||||
st1 {v23.d}[1], [x0], x1
|
||||
st1 {v24.d}[0], [x16], x1
|
||||
st1 {v24.d}[1], [x0], x1
|
||||
st1 {v25.d}[0], [x16], x1
|
||||
st1 {v25.d}[1], [x0], x1
|
||||
add x0, x0, #4
|
||||
ret x15
|
||||
endfunc
|
||||
|
||||
function lpf_v_16_8_neon
|
||||
mov x15, x30
|
||||
|
||||
sub x16, x0, x1, lsl #3
|
||||
add x16, x16, x1
|
||||
ld1 {v17.8h}, [x16], x1 // p6
|
||||
ld1 {v24.8h}, [x0], x1 // q0
|
||||
ld1 {v18.8h}, [x16], x1 // p5
|
||||
ld1 {v25.8h}, [x0], x1 // q1
|
||||
ld1 {v19.8h}, [x16], x1 // p4
|
||||
ld1 {v26.8h}, [x0], x1 // q2
|
||||
ld1 {v20.8h}, [x16], x1 // p3
|
||||
ld1 {v27.8h}, [x0], x1 // q3
|
||||
ld1 {v21.8h}, [x16], x1 // p2
|
||||
ld1 {v28.8h}, [x0], x1 // q4
|
||||
ld1 {v22.8h}, [x16], x1 // p1
|
||||
ld1 {v29.8h}, [x0], x1 // q5
|
||||
ld1 {v23.8h}, [x16], x1 // p0
|
||||
ld1 {v30.8h}, [x0], x1 // q6
|
||||
sub x0, x0, x1, lsl #3
|
||||
add x0, x0, x1
|
||||
|
||||
lpf_8_wd16
|
||||
|
||||
sub x16, x0, x1, lsl #2
|
||||
sub x16, x16, x1, lsl #1
|
||||
st1 {v0.8h}, [x16], x1 // p5
|
||||
st1 {v6.8h}, [x0], x1 // q0
|
||||
st1 {v1.8h}, [x16], x1 // p4
|
||||
st1 {v7.8h}, [x0], x1 // q1
|
||||
st1 {v2.8h}, [x16], x1 // p3
|
||||
st1 {v8.8h}, [x0], x1 // q2
|
||||
st1 {v3.8h}, [x16], x1 // p2
|
||||
st1 {v9.8h}, [x0], x1 // q3
|
||||
st1 {v4.8h}, [x16], x1 // p1
|
||||
st1 {v10.8h}, [x0], x1 // q4
|
||||
st1 {v5.8h}, [x16], x1 // p0
|
||||
st1 {v11.8h}, [x0], x1 // q5
|
||||
sub x0, x0, x1, lsl #2
|
||||
sub x0, x0, x1, lsl #1
|
||||
ret x15
|
||||
7:
|
||||
sub x16, x0, x1
|
||||
sub x16, x16, x1, lsl #1
|
||||
st1 {v21.8h}, [x16], x1 // p2
|
||||
st1 {v24.8h}, [x0], x1 // q0
|
||||
st1 {v22.8h}, [x16], x1 // p1
|
||||
st1 {v25.8h}, [x0], x1 // q1
|
||||
st1 {v23.8h}, [x16], x1 // p0
|
||||
st1 {v26.8h}, [x0], x1 // q2
|
||||
sub x0, x0, x1, lsl #1
|
||||
sub x0, x0, x1
|
||||
ret x15
|
||||
|
||||
8:
|
||||
sub x16, x0, x1, lsl #1
|
||||
st1 {v22.8h}, [x16], x1 // p1
|
||||
st1 {v24.8h}, [x0], x1 // q0
|
||||
st1 {v23.8h}, [x16], x1 // p0
|
||||
st1 {v25.8h}, [x0], x1 // q1
|
||||
sub x0, x0, x1, lsl #1
|
||||
ret x15
|
||||
endfunc
|
||||
|
||||
function lpf_h_16_8_neon
|
||||
mov x15, x30
|
||||
sub x16, x0, #16
|
||||
ld1 {v16.8h}, [x16], x1
|
||||
ld1 {v24.8h}, [x0], x1
|
||||
ld1 {v17.8h}, [x16], x1
|
||||
ld1 {v25.8h}, [x0], x1
|
||||
ld1 {v18.8h}, [x16], x1
|
||||
ld1 {v26.8h}, [x0], x1
|
||||
ld1 {v19.8h}, [x16], x1
|
||||
ld1 {v27.8h}, [x0], x1
|
||||
ld1 {v20.8h}, [x16], x1
|
||||
ld1 {v28.8h}, [x0], x1
|
||||
ld1 {v21.8h}, [x16], x1
|
||||
ld1 {v29.8h}, [x0], x1
|
||||
ld1 {v22.8h}, [x16], x1
|
||||
ld1 {v30.8h}, [x0], x1
|
||||
ld1 {v23.8h}, [x16], x1
|
||||
ld1 {v31.8h}, [x0], x1
|
||||
|
||||
transpose_8x8h v16, v17, v18, v19, v20, v21, v22, v23, v0, v1
|
||||
transpose_8x8h v24, v25, v26, v27, v28, v29, v30, v31, v0, v1
|
||||
|
||||
lpf_8_wd16
|
||||
|
||||
sub x0, x0, x1, lsl #3
|
||||
sub x16, x0, #16
|
||||
|
||||
transpose_8x8h v16, v17, v0, v1, v2, v3, v4, v5, v18, v19
|
||||
transpose_8x8h v6, v7, v8, v9, v10, v11, v30, v31, v18, v19
|
||||
|
||||
st1 {v16.8h}, [x16], x1
|
||||
st1 {v6.8h}, [x0], x1
|
||||
st1 {v17.8h}, [x16], x1
|
||||
st1 {v7.8h}, [x0], x1
|
||||
st1 {v0.8h}, [x16], x1
|
||||
st1 {v8.8h}, [x0], x1
|
||||
st1 {v1.8h}, [x16], x1
|
||||
st1 {v9.8h}, [x0], x1
|
||||
st1 {v2.8h}, [x16], x1
|
||||
st1 {v10.8h}, [x0], x1
|
||||
st1 {v3.8h}, [x16], x1
|
||||
st1 {v11.8h}, [x0], x1
|
||||
st1 {v4.8h}, [x16], x1
|
||||
st1 {v30.8h}, [x0], x1
|
||||
st1 {v5.8h}, [x16], x1
|
||||
st1 {v31.8h}, [x0], x1
|
||||
ret x15
|
||||
|
||||
7:
|
||||
sub x16, x0, x1, lsl #3
|
||||
sub x16, x16, #8
|
||||
transpose_8x8h v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
|
||||
add x0, x16, x1, lsl #2
|
||||
|
||||
st1 {v20.8h}, [x16], x1
|
||||
st1 {v24.8h}, [x0], x1
|
||||
st1 {v21.8h}, [x16], x1
|
||||
st1 {v25.8h}, [x0], x1
|
||||
st1 {v22.8h}, [x16], x1
|
||||
st1 {v26.8h}, [x0], x1
|
||||
st1 {v23.8h}, [x16], x1
|
||||
st1 {v27.8h}, [x0], x1
|
||||
add x0, x0, #8
|
||||
ret x15
|
||||
8:
|
||||
sub x16, x0, x1, lsl #3
|
||||
sub x16, x16, #4
|
||||
transpose_4x8h v22, v23, v24, v25, v26, v27, v28, v29
|
||||
add x0, x16, x1, lsl #2
|
||||
|
||||
st1 {v22.d}[0], [x16], x1
|
||||
st1 {v22.d}[1], [x0], x1
|
||||
st1 {v23.d}[0], [x16], x1
|
||||
st1 {v23.d}[1], [x0], x1
|
||||
st1 {v24.d}[0], [x16], x1
|
||||
st1 {v24.d}[1], [x0], x1
|
||||
st1 {v25.d}[0], [x16], x1
|
||||
st1 {v25.d}[1], [x0], x1
|
||||
add x0, x0, #4
|
||||
ret x15
|
||||
endfunc
|
||||
|
||||
// void dav1d_lpf_v_sb_y_16bpc_neon(pixel *dst, const ptrdiff_t stride,
|
||||
// const uint32_t *const vmask,
|
||||
// const uint8_t (*l)[4], ptrdiff_t b4_stride,
|
||||
// const Av1FilterLUT *lut, const int w,
|
||||
// const int bitdepth_max)
|
||||
|
||||
.macro lpf_func dir, type
|
||||
function lpf_\dir\()_sb_\type\()_16bpc_neon, export=1
|
||||
mov x11, x30
|
||||
mov w8, w7 // bitdepth_max
|
||||
clz w9, w8
|
||||
mov w10, #24
|
||||
sub w9, w10, w9 // bitdepth_min_8
|
||||
stp d8, d9, [sp, #-0x40]!
|
||||
stp d10, d11, [sp, #0x10]
|
||||
stp d12, d13, [sp, #0x20]
|
||||
stp d14, d15, [sp, #0x30]
|
||||
ldp w6, w7, [x2] // vmask[0], vmask[1]
|
||||
.ifc \type, y
|
||||
ldr w2, [x2, #8] // vmask[2]
|
||||
.endif
|
||||
add x5, x5, #128 // Move to sharp part of lut
|
||||
.ifc \type, y
|
||||
orr w7, w7, w2 // vmask[1] |= vmask[2]
|
||||
.endif
|
||||
.ifc \dir, v
|
||||
sub x4, x3, x4, lsl #2
|
||||
.else
|
||||
sub x3, x3, #4
|
||||
lsl x4, x4, #2
|
||||
.endif
|
||||
orr w6, w6, w7 // vmask[0] |= vmask[1]
|
||||
|
||||
1:
|
||||
tst w6, #0x03
|
||||
.ifc \dir, v
|
||||
ld1 {v0.8b}, [x4], #8
|
||||
ld1 {v1.8b}, [x3], #8
|
||||
.else
|
||||
ld2 {v0.s,v1.s}[0], [x3], x4
|
||||
ld2 {v0.s,v1.s}[1], [x3], x4
|
||||
.endif
|
||||
b.eq 7f // if (!(vm & bits)) continue;
|
||||
|
||||
ld1r {v5.8b}, [x5] // sharp[0]
|
||||
add x5, x5, #8
|
||||
movi v2.2s, #0xff
|
||||
dup v13.2s, w6 // vmask[0]
|
||||
dup v31.8h, w9 // bitdepth_min_8
|
||||
|
||||
and v0.8b, v0.8b, v2.8b // Keep only lowest byte in each 32 bit word
|
||||
and v1.8b, v1.8b, v2.8b
|
||||
cmtst v3.8b, v1.8b, v2.8b // Check for nonzero values in l[0][0]
|
||||
movi v4.8b, #1
|
||||
ld1r {v6.8b}, [x5] // sharp[1]
|
||||
sub x5, x5, #8
|
||||
bif v1.8b, v0.8b, v3.8b // if (!l[0][0]) L = l[offset][0]
|
||||
cmtst v2.2s, v1.2s, v2.2s // L != 0
|
||||
mul v1.2s, v1.2s, v4.2s // L
|
||||
.ifc \type, y
|
||||
dup v15.2s, w2 // vmask[2]
|
||||
.endif
|
||||
dup v14.2s, w7 // vmask[1]
|
||||
mov x16, v2.d[0]
|
||||
cmp x16, #0
|
||||
b.eq 7f // if (!L) continue;
|
||||
neg v5.8b, v5.8b // -sharp[0]
|
||||
movrel x16, word_12
|
||||
ushr v12.8b, v1.8b, #4 // H
|
||||
ld1 {v16.2s}, [x16]
|
||||
sshl v3.8b, v1.8b, v5.8b // L >> sharp[0]
|
||||
.ifc \type, y
|
||||
cmtst v15.2s, v15.2s, v16.2s // if (vmask[2] & bits)
|
||||
.endif
|
||||
movi v7.8b, #2
|
||||
umin v3.8b, v3.8b, v6.8b // imin(L >> sharp[0], sharp[1])
|
||||
add v0.8b, v1.8b, v7.8b // L + 2
|
||||
umax v11.8b, v3.8b, v4.8b // imax(imin(), 1) = limit = I
|
||||
add v0.8b, v0.8b, v0.8b // 2*(L + 2)
|
||||
cmtst v14.2s, v14.2s, v16.2s // if (vmask[1] & bits)
|
||||
uxtl v12.8h, v12.8b
|
||||
add v10.8b, v0.8b, v11.8b // 2*(L + 2) + limit = E
|
||||
cmtst v13.2s, v13.2s, v16.2s // if (vmask[0] & bits)
|
||||
uxtl v11.8h, v11.8b
|
||||
uxtl v10.8h, v10.8b
|
||||
and v13.8b, v13.8b, v2.8b // vmask[0] &= L != 0
|
||||
sxtl v14.8h, v14.8b
|
||||
sxtl v13.8h, v13.8b
|
||||
.ifc \type, y
|
||||
sxtl v15.8h, v15.8b
|
||||
.endif
|
||||
ushl v12.8h, v12.8h, v31.8h
|
||||
ushl v11.8h, v11.8h, v31.8h
|
||||
ushl v10.8h, v10.8h, v31.8h
|
||||
|
||||
.ifc \type, y
|
||||
tst w2, #0x03
|
||||
b.eq 2f
|
||||
// wd16
|
||||
bl lpf_\dir\()_16_8_neon
|
||||
b 8f
|
||||
2:
|
||||
.endif
|
||||
tst w7, #0x03
|
||||
b.eq 3f
|
||||
.ifc \type, y
|
||||
// wd8
|
||||
bl lpf_\dir\()_8_8_neon
|
||||
.else
|
||||
// wd6
|
||||
bl lpf_\dir\()_6_8_neon
|
||||
.endif
|
||||
b 8f
|
||||
3:
|
||||
// wd4
|
||||
bl lpf_\dir\()_4_8_neon
|
||||
.ifc \dir, h
|
||||
b 8f
|
||||
7:
|
||||
// For dir h, the functions above increment x0.
|
||||
// If the whole function is skipped, increment it here instead.
|
||||
add x0, x0, x1, lsl #3
|
||||
.else
|
||||
7:
|
||||
.endif
|
||||
8:
|
||||
lsr w6, w6, #2 // vmask[0] >>= 2
|
||||
lsr w7, w7, #2 // vmask[1] >>= 2
|
||||
.ifc \type, y
|
||||
lsr w2, w2, #2 // vmask[2] >>= 2
|
||||
.endif
|
||||
.ifc \dir, v
|
||||
add x0, x0, #16
|
||||
.else
|
||||
// For dir h, x0 is returned incremented
|
||||
.endif
|
||||
cbnz w6, 1b
|
||||
|
||||
ldp d14, d15, [sp, #0x30]
|
||||
ldp d12, d13, [sp, #0x20]
|
||||
ldp d10, d11, [sp, #0x10]
|
||||
ldp d8, d9, [sp], 0x40
|
||||
ret x11
|
||||
endfunc
|
||||
.endm
|
||||
|
||||
lpf_func v, y
|
||||
lpf_func h, y
|
||||
lpf_func v, uv
|
||||
lpf_func h, uv
|
||||
|
||||
const word_12
|
||||
.word 1, 2
|
||||
endconst
|
||||
1303
media/libdav1d/src/src/arm/64/looprestoration.S
Normal file
1303
media/libdav1d/src/src/arm/64/looprestoration.S
Normal file
File diff suppressed because it is too large
Load diff
1388
media/libdav1d/src/src/arm/64/looprestoration16.S
Normal file
1388
media/libdav1d/src/src/arm/64/looprestoration16.S
Normal file
File diff suppressed because it is too large
Load diff
334
media/libdav1d/src/src/arm/64/looprestoration_common.S
Normal file
334
media/libdav1d/src/src/arm/64/looprestoration_common.S
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
// Series of LUTs for efficiently computing sgr's 1 - x/(x+1) table.
|
||||
// In the comments, let RefTable denote the original, reference table.
|
||||
const x_by_x_tables
|
||||
// RangeMins
|
||||
//
|
||||
// Min(RefTable[i*8:i*8+8])
|
||||
// First two values are zeroed.
|
||||
//
|
||||
// Lookup using RangeMins[(x >> 3)]
|
||||
.byte 0, 0, 11, 8, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2
|
||||
.byte 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
|
||||
|
||||
// DiffMasks
|
||||
//
|
||||
// This contains a bit pattern, indicating at which index positions the value of RefTable changes. For each range
|
||||
// in the RangeMins table (covering 8 RefTable entries), we have one byte; each bit indicates whether the value of
|
||||
// RefTable changes at that particular index.
|
||||
// Using popcount, we can integrate the diff bit field. By shifting away bits in a byte, we can refine the range of
|
||||
// the integral. Finally, adding the integral to RangeMins[(x>>3)] reconstructs RefTable (for x > 15).
|
||||
//
|
||||
// Lookup using DiffMasks[(x >> 3)]
|
||||
.byte 0x00, 0x00, 0xD4, 0x44
|
||||
.byte 0x42, 0x04, 0x00, 0x00
|
||||
.byte 0x00, 0x80, 0x00, 0x00
|
||||
.byte 0x04, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x40, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x02
|
||||
// Binary form:
|
||||
// 0b00000000, 0b00000000, 0b11010100, 0b01000100
|
||||
// 0b01000010, 0b00000100, 0b00000000, 0b00000000
|
||||
// 0b00000000, 0b10000000, 0b00000000, 0b00000000
|
||||
// 0b00000100, 0b00000000, 0b00000000, 0b00000000
|
||||
// 0b00000000, 0b00000000, 0b00000000, 0b00000000
|
||||
// 0b00000000, 0b01000000, 0b00000000, 0b00000000
|
||||
// 0b00000000, 0b00000000, 0b00000000, 0b00000000
|
||||
// 0b00000000, 0b00000000, 0b00000000, 0b00000010
|
||||
|
||||
// RefLo
|
||||
//
|
||||
// RefTable[0:16]
|
||||
// i.e. First 16 elements of the original table.
|
||||
// Add to the sum obtained in the rest of the other lut logic to include the first 16 bytes of RefTable.
|
||||
//
|
||||
// Lookup using RangeMins[x] (tbl will replace x > 15 with 0)
|
||||
.byte 255, 128, 85, 64, 51, 43, 37, 32, 28, 26, 23, 21, 20, 18, 17, 16
|
||||
|
||||
// Pseudo assembly
|
||||
//
|
||||
// hi_bits = x >> 3
|
||||
// tbl ref, {RefLo}, x
|
||||
// tbl diffs, {DiffMasks[0:16], DiffMasks[16:32]}, hi_bits
|
||||
// tbl min, {RangeMins[0:16], RangeMins[16:32]}, hi_bits
|
||||
// lo_bits = x & 0x7
|
||||
// diffs = diffs << lo_bits
|
||||
// ref = ref + min
|
||||
// integral = popcnt(diffs)
|
||||
// ref = ref + integral
|
||||
// return ref
|
||||
endconst
|
||||
|
||||
// void dav1d_sgr_box3_vert_neon(int32_t **sumsq, int16_t **sum,
|
||||
// int32_t *AA, int16_t *BB,
|
||||
// const int w, const int s,
|
||||
// const int bitdepth_max);
|
||||
function sgr_box3_vert_neon, export=1
|
||||
stp d8, d9, [sp, #-0x40]!
|
||||
stp d10, d11, [sp, #0x10]
|
||||
stp d12, d13, [sp, #0x20]
|
||||
stp d14, d15, [sp, #0x30]
|
||||
|
||||
add w4, w4, #2
|
||||
clz w9, w6 // bitdepth_max
|
||||
dup v28.4s, w5 // strength
|
||||
|
||||
ldp x5, x6, [x0]
|
||||
ldr x0, [x0, #16]
|
||||
ldp x7, x8, [x1]
|
||||
ldr x1, [x1, #16]
|
||||
|
||||
movi v31.4s, #9 // n
|
||||
|
||||
sub w9, w9, #24 // -bitdepth_min_8
|
||||
movrel x12, x_by_x_tables
|
||||
mov w13, #455 // one_by_x
|
||||
ld1 {v24.16b, v25.16b, v26.16b, v27.16b}, [x12] // RangeMins, DiffMasks
|
||||
movi v22.16b, #0x7
|
||||
ldr q23, [x12, #64] //RefLo
|
||||
dup v6.8h, w9 // -bitdepth_min_8
|
||||
saddl v7.4s, v6.4h, v6.4h // -2*bitdepth_min_8
|
||||
dup v30.4s, w13 // one_by_x
|
||||
|
||||
ld1 {v8.4s, v9.4s, v10.4s, v11.4s}, [x5], #64
|
||||
ld1 {v12.4s, v13.4s, v14.4s, v15.4s}, [x6], #64
|
||||
ld1 {v16.4s, v17.4s, v18.4s, v19.4s}, [x0], #64
|
||||
ld1 {v20.8h, v21.8h}, [x8], #32
|
||||
ld1 {v0.8h, v1.8h}, [x7], #32
|
||||
1:
|
||||
ld1 {v2.8h, v3.8h}, [x1], #32
|
||||
add v8.4s, v8.4s, v12.4s
|
||||
add v9.4s, v9.4s, v13.4s
|
||||
add v10.4s, v10.4s, v14.4s
|
||||
add v11.4s, v11.4s, v15.4s
|
||||
add v0.8h, v0.8h, v20.8h
|
||||
add v1.8h, v1.8h, v21.8h
|
||||
|
||||
add v16.4s, v16.4s, v8.4s
|
||||
add v17.4s, v17.4s, v9.4s
|
||||
add v18.4s, v18.4s, v10.4s
|
||||
add v19.4s, v19.4s, v11.4s
|
||||
add v4.8h, v2.8h, v0.8h
|
||||
add v5.8h, v3.8h, v1.8h
|
||||
|
||||
srshl v16.4s, v16.4s, v7.4s
|
||||
srshl v17.4s, v17.4s, v7.4s
|
||||
srshl v18.4s, v18.4s, v7.4s
|
||||
srshl v19.4s, v19.4s, v7.4s
|
||||
srshl v9.8h, v4.8h, v6.8h
|
||||
srshl v13.8h, v5.8h, v6.8h
|
||||
mul v16.4s, v16.4s, v31.4s // a * n
|
||||
mul v17.4s, v17.4s, v31.4s // a * n
|
||||
mul v18.4s, v18.4s, v31.4s // a * n
|
||||
mul v19.4s, v19.4s, v31.4s // a * n
|
||||
umull v8.4s, v9.4h, v9.4h // b * b
|
||||
umull2 v9.4s, v9.8h, v9.8h // b * b
|
||||
umull v12.4s, v13.4h, v13.4h // b * b
|
||||
umull2 v13.4s, v13.8h, v13.8h // b * b
|
||||
uqsub v16.4s, v16.4s, v8.4s // imax(a * n - b * b, 0)
|
||||
uqsub v17.4s, v17.4s, v9.4s // imax(a * n - b * b, 0)
|
||||
uqsub v18.4s, v18.4s, v12.4s // imax(a * n - b * b, 0)
|
||||
uqsub v19.4s, v19.4s, v13.4s // imax(a * n - b * b, 0)
|
||||
mul v16.4s, v16.4s, v28.4s // p * s
|
||||
mul v17.4s, v17.4s, v28.4s // p * s
|
||||
mul v18.4s, v18.4s, v28.4s // p * s
|
||||
mul v19.4s, v19.4s, v28.4s // p * s
|
||||
uqshrn v16.4h, v16.4s, #16
|
||||
uqshrn2 v16.8h, v17.4s, #16
|
||||
uqshrn v18.4h, v18.4s, #16
|
||||
uqshrn2 v18.8h, v19.4s, #16
|
||||
uqrshrn v1.8b, v16.8h, #4 // imin(z, 255)
|
||||
uqrshrn2 v1.16b, v18.8h, #4 // imin(z, 255)
|
||||
|
||||
ld1 {v16.4s, v17.4s}, [x0], #32
|
||||
subs w4, w4, #16
|
||||
|
||||
ushr v0.16b, v1.16b, #3
|
||||
ld1 {v8.4s, v9.4s}, [x5], #32
|
||||
tbl v2.16b, {v26.16b, v27.16b}, v0.16b // RangeMins
|
||||
tbl v0.16b, {v24.16b, v25.16b}, v0.16b // DiffMasks
|
||||
tbl v3.16b, {v23.16b}, v1.16b // RefLo
|
||||
and v1.16b, v1.16b, v22.16b
|
||||
ld1 {v12.4s, v13.4s}, [x6], #32
|
||||
ushl v1.16b, v2.16b, v1.16b
|
||||
ld1 {v20.8h, v21.8h}, [x8], #32
|
||||
add v3.16b, v3.16b, v0.16b
|
||||
cnt v1.16b, v1.16b
|
||||
ld1 {v18.4s, v19.4s}, [x0], #32
|
||||
add v3.16b, v3.16b, v1.16b
|
||||
ld1 {v10.4s, v11.4s}, [x5], #32
|
||||
uxtl v0.8h, v3.8b // x
|
||||
uxtl2 v1.8h, v3.16b // x
|
||||
|
||||
ld1 {v14.4s, v15.4s}, [x6], #32
|
||||
|
||||
umull v2.4s, v0.4h, v4.4h // x * BB[i]
|
||||
umull2 v3.4s, v0.8h, v4.8h // x * BB[i]
|
||||
umull v4.4s, v1.4h, v5.4h // x * BB[i]
|
||||
umull2 v5.4s, v1.8h, v5.8h // x * BB[i]
|
||||
mul v2.4s, v2.4s, v30.4s // x * BB[i] * sgr_one_by_x
|
||||
mul v3.4s, v3.4s, v30.4s // x * BB[i] * sgr_one_by_x
|
||||
mul v4.4s, v4.4s, v30.4s // x * BB[i] * sgr_one_by_x
|
||||
mul v5.4s, v5.4s, v30.4s // x * BB[i] * sgr_one_by_x
|
||||
st1 {v0.8h, v1.8h}, [x3], #32
|
||||
ld1 {v0.8h, v1.8h}, [x7], #32
|
||||
srshr v2.4s, v2.4s, #12 // AA[i]
|
||||
srshr v3.4s, v3.4s, #12 // AA[i]
|
||||
srshr v4.4s, v4.4s, #12 // AA[i]
|
||||
srshr v5.4s, v5.4s, #12 // AA[i]
|
||||
|
||||
st1 {v2.4s, v3.4s, v4.4s, v5.4s}, [x2], #64
|
||||
b.gt 1b
|
||||
|
||||
ldp d14, d15, [sp, #0x30]
|
||||
ldp d12, d13, [sp, #0x20]
|
||||
ldp d10, d11, [sp, #0x10]
|
||||
ldp d8, d9, [sp], 0x40
|
||||
ret
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_box5_vert_neon(int32_t **sumsq, int16_t **sum,
|
||||
// int32_t *AA, int16_t *BB,
|
||||
// const int w, const int s,
|
||||
// const int bitdepth_max);
|
||||
function sgr_box5_vert_neon, export=1
|
||||
stp d8, d9, [sp, #-0x30]!
|
||||
stp d10, d11, [sp, #0x10]
|
||||
stp d12, d13, [sp, #0x20]
|
||||
|
||||
add w4, w4, #2
|
||||
clz w15, w6 // bitdepth_max
|
||||
dup v28.4s, w5 // strength
|
||||
|
||||
ldp x5, x6, [x0]
|
||||
ldp x7, x8, [x0, #16]
|
||||
ldr x0, [x0, #32]
|
||||
ldp x9, x10, [x1]
|
||||
ldp x11, x12, [x1, #16]
|
||||
ldr x1, [x1, #32]
|
||||
|
||||
movi v31.4s, #25 // n
|
||||
|
||||
sub w15, w15, #24 // -bitdepth_min_8
|
||||
movrel x13, x_by_x_tables
|
||||
movi v30.4s, #164
|
||||
ld1 {v24.16b, v25.16b, v26.16b, v27.16b}, [x13] // RangeMins, DiffMasks
|
||||
dup v6.8h, w15 // -bitdepth_min_8
|
||||
movi v19.8b, #0x7
|
||||
ldr q18, [x13, #64] // RefLo
|
||||
saddl v7.4s, v6.4h, v6.4h // -2*bitdepth_min_8
|
||||
|
||||
ld1 {v8.4s, v9.4s}, [x5], #32
|
||||
ld1 {v10.4s, v11.4s}, [x6], #32
|
||||
ld1 {v12.4s, v13.4s}, [x7], #32
|
||||
ld1 {v16.4s, v17.4s}, [x8], #32
|
||||
ld1 {v20.8h}, [x9], #16
|
||||
ld1 {v21.8h}, [x10], #16
|
||||
ld1 {v22.8h}, [x11], #16
|
||||
ld1 {v23.8h}, [x12], #16
|
||||
ld1 {v0.4s, v1.4s}, [x0], #32
|
||||
ld1 {v2.8h}, [x1], #16
|
||||
|
||||
1:
|
||||
add v8.4s, v8.4s, v10.4s
|
||||
add v9.4s, v9.4s, v11.4s
|
||||
add v12.4s, v12.4s, v16.4s
|
||||
add v13.4s, v13.4s, v17.4s
|
||||
|
||||
add v20.8h, v20.8h, v21.8h
|
||||
add v22.8h, v22.8h, v23.8h
|
||||
|
||||
add v0.4s, v0.4s, v8.4s
|
||||
add v1.4s, v1.4s, v9.4s
|
||||
add v2.8h, v2.8h, v20.8h
|
||||
|
||||
add v0.4s, v0.4s, v12.4s
|
||||
add v1.4s, v1.4s, v13.4s
|
||||
add v2.8h, v2.8h, v22.8h
|
||||
|
||||
subs w4, w4, #8
|
||||
|
||||
srshl v0.4s, v0.4s, v7.4s
|
||||
srshl v1.4s, v1.4s, v7.4s
|
||||
srshl v4.8h, v2.8h, v6.8h
|
||||
mul v0.4s, v0.4s, v31.4s // a * n
|
||||
mul v1.4s, v1.4s, v31.4s // a * n
|
||||
umull v3.4s, v4.4h, v4.4h // b * b
|
||||
umull2 v4.4s, v4.8h, v4.8h // b * b
|
||||
uqsub v0.4s, v0.4s, v3.4s // imax(a * n - b * b, 0)
|
||||
uqsub v1.4s, v1.4s, v4.4s // imax(a * n - b * b, 0)
|
||||
mul v0.4s, v0.4s, v28.4s // p * s
|
||||
mul v1.4s, v1.4s, v28.4s // p * s
|
||||
ld1 {v8.4s, v9.4s}, [x5], #32
|
||||
uqshrn v0.4h, v0.4s, #16
|
||||
uqshrn2 v0.8h, v1.4s, #16
|
||||
ld1 {v10.4s, v11.4s}, [x6], #32
|
||||
uqrshrn v0.8b, v0.8h, #4 // imin(z, 255)
|
||||
|
||||
ld1 {v12.4s, v13.4s}, [x7], #32
|
||||
|
||||
ushr v1.8b, v0.8b, #3
|
||||
ld1 {v16.4s, v17.4s}, [x8], #32
|
||||
tbl v5.8b, {v26.16b, v27.16b}, v1.8b // RangeMins
|
||||
tbl v1.8b, {v24.16b, v25.16b}, v1.8b // DiffMasks
|
||||
tbl v4.8b, {v18.16b}, v0.8b // RefLo
|
||||
and v0.8b, v0.8b, v19.8b
|
||||
ld1 {v20.8h}, [x9], #16
|
||||
ushl v5.8b, v5.8b, v0.8b
|
||||
add v4.8b, v4.8b, v1.8b
|
||||
ld1 {v21.8h}, [x10], #16
|
||||
cnt v5.8b, v5.8b
|
||||
ld1 {v22.8h}, [x11], #16
|
||||
add v5.8b, v4.8b, v5.8b
|
||||
ld1 {v23.8h}, [x12], #16
|
||||
uxtl v5.8h, v5.8b // x
|
||||
|
||||
ld1 {v0.4s, v1.4s}, [x0], #32
|
||||
umull v3.4s, v5.4h, v2.4h // x * BB[i]
|
||||
umull2 v4.4s, v5.8h, v2.8h // x * BB[i]
|
||||
mul v3.4s, v3.4s, v30.4s // x * BB[i] * sgr_one_by_x
|
||||
mul v4.4s, v4.4s, v30.4s // x * BB[i] * sgr_one_by_x
|
||||
srshr v3.4s, v3.4s, #12 // AA[i]
|
||||
srshr v4.4s, v4.4s, #12 // AA[i]
|
||||
ld1 {v2.8h}, [x1], #16
|
||||
|
||||
st1 {v3.4s, v4.4s}, [x2], #32
|
||||
st1 {v5.8h}, [x3], #16
|
||||
b.gt 1b
|
||||
|
||||
ldp d12, d13, [sp, #0x20]
|
||||
ldp d10, d11, [sp, #0x10]
|
||||
ldp d8, d9, [sp], 0x30
|
||||
ret
|
||||
endfunc
|
||||
704
media/libdav1d/src/src/arm/64/looprestoration_tmpl.S
Normal file
704
media/libdav1d/src/src/arm/64/looprestoration_tmpl.S
Normal file
|
|
@ -0,0 +1,704 @@
|
|||
/*
|
||||
* Copyright © 2018, VideoLAN and dav1d authors
|
||||
* Copyright © 2018, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
|
||||
#define FILTER_OUT_STRIDE 384
|
||||
|
||||
.macro sgr_funcs bpc
|
||||
// void dav1d_sgr_finish_filter1_2rows_Xbpc_neon(int16_t *tmp,
|
||||
// const pixel *src,
|
||||
// const ptrdiff_t src_stride,
|
||||
// const int32_t **a,
|
||||
// const int16_t **b,
|
||||
// const int w, const int h);
|
||||
function sgr_finish_filter1_2rows_\bpc\()bpc_neon, export=1
|
||||
stp d8, d9, [sp, #-0x40]!
|
||||
stp d10, d11, [sp, #0x10]
|
||||
stp d12, d13, [sp, #0x20]
|
||||
stp d14, d15, [sp, #0x30]
|
||||
|
||||
ldp x7, x8, [x3]
|
||||
ldp x9, x3, [x3, #16]
|
||||
ldp x10, x11, [x4]
|
||||
ldp x12, x4, [x4, #16]
|
||||
|
||||
mov x13, #FILTER_OUT_STRIDE
|
||||
cmp w6, #1
|
||||
add x2, x1, x2 // src + stride
|
||||
csel x2, x1, x2, le // if (h <= 1) x2 = x1
|
||||
add x13, x0, x13, lsl #1
|
||||
|
||||
movi v30.8h, #3
|
||||
movi v31.4s, #3
|
||||
1:
|
||||
ld1 {v0.8h, v1.8h}, [x10], #32
|
||||
ld1 {v2.8h, v3.8h}, [x11], #32
|
||||
ld1 {v4.8h, v5.8h}, [x12], #32
|
||||
ld1 {v6.8h, v7.8h}, [x4], #32
|
||||
ld1 {v16.4s, v17.4s, v18.4s}, [x7], #48
|
||||
ld1 {v19.4s, v20.4s, v21.4s}, [x8], #48
|
||||
ld1 {v22.4s, v23.4s, v24.4s}, [x9], #48
|
||||
ld1 {v25.4s, v26.4s, v27.4s}, [x3], #48
|
||||
|
||||
2:
|
||||
ext v8.16b, v0.16b, v1.16b, #2 // [0][1]
|
||||
ext v9.16b, v2.16b, v3.16b, #2 // [1][1]
|
||||
ext v10.16b, v4.16b, v5.16b, #2 // [2][1]
|
||||
ext v11.16b, v0.16b, v1.16b, #4 // [0][2]
|
||||
ext v12.16b, v2.16b, v3.16b, #4 // [1][2]
|
||||
ext v13.16b, v4.16b, v5.16b, #4 // [2][2]
|
||||
|
||||
add v14.8h, v2.8h, v8.8h // [1][0] + [0][1]
|
||||
add v15.8h, v9.8h, v10.8h // [1][1] + [2][1]
|
||||
|
||||
add v28.8h, v0.8h, v11.8h // [0][0] + [0][2]
|
||||
add v14.8h, v14.8h, v12.8h // () + [1][2]
|
||||
add v29.8h, v4.8h, v13.8h // [2][0] + [2][2]
|
||||
|
||||
ext v8.16b, v6.16b, v7.16b, #2 // [3][1]
|
||||
ext v11.16b, v6.16b, v7.16b, #4 // [3][2]
|
||||
|
||||
add v14.8h, v14.8h, v15.8h // mid
|
||||
add v15.8h, v28.8h, v29.8h // corners
|
||||
|
||||
add v28.8h, v4.8h, v9.8h // [2][0] + [1][1]
|
||||
add v29.8h, v10.8h, v8.8h // [2][1] + [3][1]
|
||||
|
||||
add v2.8h, v2.8h, v12.8h // [1][0] + [1][2]
|
||||
add v28.8h, v28.8h, v13.8h // () + [2][2]
|
||||
add v4.8h, v6.8h, v11.8h // [3][0] + [3][2]
|
||||
|
||||
add v0.8h, v28.8h, v29.8h // mid
|
||||
add v2.8h, v2.8h, v4.8h // corners
|
||||
|
||||
shl v4.8h, v14.8h, #2
|
||||
mla v4.8h, v15.8h, v30.8h // * 3 -> a
|
||||
|
||||
shl v0.8h, v0.8h, #2
|
||||
mla v0.8h, v2.8h, v30.8h // * 3 -> a
|
||||
|
||||
ext v8.16b, v16.16b, v17.16b, #4 // [0][1]
|
||||
ext v9.16b, v17.16b, v18.16b, #4
|
||||
ext v10.16b, v16.16b, v17.16b, #8 // [0][2]
|
||||
ext v11.16b, v17.16b, v18.16b, #8
|
||||
ext v12.16b, v19.16b, v20.16b, #4 // [1][1]
|
||||
ext v13.16b, v20.16b, v21.16b, #4
|
||||
add v8.4s, v8.4s, v19.4s // [0][1] + [1][0]
|
||||
add v9.4s, v9.4s, v20.4s
|
||||
add v16.4s, v16.4s, v10.4s // [0][0] + [0][2]
|
||||
add v17.4s, v17.4s, v11.4s
|
||||
ext v14.16b, v19.16b, v20.16b, #8 // [1][2]
|
||||
ext v15.16b, v20.16b, v21.16b, #8
|
||||
add v16.4s, v16.4s, v22.4s // () + [2][0]
|
||||
add v17.4s, v17.4s, v23.4s
|
||||
add v28.4s, v12.4s, v14.4s // [1][1] + [1][2]
|
||||
add v29.4s, v13.4s, v15.4s
|
||||
ext v10.16b, v22.16b, v23.16b, #4 // [2][1]
|
||||
ext v11.16b, v23.16b, v24.16b, #4
|
||||
add v8.4s, v8.4s, v28.4s // mid (incomplete)
|
||||
add v9.4s, v9.4s, v29.4s
|
||||
|
||||
add v19.4s, v19.4s, v14.4s // [1][0] + [1][2]
|
||||
add v20.4s, v20.4s, v15.4s
|
||||
add v14.4s, v22.4s, v12.4s // [2][0] + [1][1]
|
||||
add v15.4s, v23.4s, v13.4s
|
||||
|
||||
ext v12.16b, v22.16b, v23.16b, #8 // [2][2]
|
||||
ext v13.16b, v23.16b, v24.16b, #8
|
||||
ext v28.16b, v25.16b, v26.16b, #4 // [3][1]
|
||||
ext v29.16b, v26.16b, v27.16b, #4
|
||||
add v8.4s, v8.4s, v10.4s // () + [2][1] = mid
|
||||
add v9.4s, v9.4s, v11.4s
|
||||
add v14.4s, v14.4s, v10.4s // () + [2][1]
|
||||
add v15.4s, v15.4s, v11.4s
|
||||
ext v10.16b, v25.16b, v26.16b, #8 // [3][2]
|
||||
ext v11.16b, v26.16b, v27.16b, #8
|
||||
add v16.4s, v16.4s, v12.4s // () + [2][2] = corner
|
||||
add v17.4s, v17.4s, v13.4s
|
||||
|
||||
add v12.4s, v12.4s, v28.4s // [2][2] + [3][1]
|
||||
add v13.4s, v13.4s, v29.4s
|
||||
add v25.4s, v25.4s, v10.4s // [3][0] + [3][2]
|
||||
add v26.4s, v26.4s, v11.4s
|
||||
|
||||
add v14.4s, v14.4s, v12.4s // mid
|
||||
add v15.4s, v15.4s, v13.4s
|
||||
add v19.4s, v19.4s, v25.4s // corner
|
||||
add v20.4s, v20.4s, v26.4s
|
||||
|
||||
.if \bpc == 8
|
||||
ld1 {v25.8b}, [x1], #8 // src
|
||||
ld1 {v26.8b}, [x2], #8
|
||||
.else
|
||||
ld1 {v25.8h}, [x1], #16 // src
|
||||
ld1 {v26.8h}, [x2], #16
|
||||
.endif
|
||||
|
||||
shl v8.4s, v8.4s, #2
|
||||
shl v9.4s, v9.4s, #2
|
||||
mla v8.4s, v16.4s, v31.4s // * 3 -> b
|
||||
mla v9.4s, v17.4s, v31.4s
|
||||
|
||||
.if \bpc == 8
|
||||
uxtl v25.8h, v25.8b // src
|
||||
uxtl v26.8h, v26.8b
|
||||
.endif
|
||||
|
||||
shl v14.4s, v14.4s, #2
|
||||
shl v15.4s, v15.4s, #2
|
||||
mla v14.4s, v19.4s, v31.4s // * 3 -> b
|
||||
mla v15.4s, v20.4s, v31.4s
|
||||
|
||||
umlsl v8.4s, v4.4h, v25.4h // b - a * src
|
||||
umlsl2 v9.4s, v4.8h, v25.8h
|
||||
umlsl v14.4s, v0.4h, v26.4h // b - a * src
|
||||
umlsl2 v15.4s, v0.8h, v26.8h
|
||||
mov v0.16b, v1.16b
|
||||
rshrn v8.4h, v8.4s, #9
|
||||
rshrn2 v8.8h, v9.4s, #9
|
||||
mov v2.16b, v3.16b
|
||||
rshrn v14.4h, v14.4s, #9
|
||||
rshrn2 v14.8h, v15.4s, #9
|
||||
subs w5, w5, #8
|
||||
mov v4.16b, v5.16b
|
||||
st1 {v8.8h}, [x0], #16
|
||||
mov v6.16b, v7.16b
|
||||
st1 {v14.8h}, [x13], #16
|
||||
|
||||
b.le 3f
|
||||
mov v16.16b, v18.16b
|
||||
mov v19.16b, v21.16b
|
||||
mov v22.16b, v24.16b
|
||||
mov v25.16b, v27.16b
|
||||
ld1 {v1.8h}, [x10], #16
|
||||
ld1 {v3.8h}, [x11], #16
|
||||
ld1 {v5.8h}, [x12], #16
|
||||
ld1 {v7.8h}, [x4], #16
|
||||
ld1 {v17.4s, v18.4s}, [x7], #32
|
||||
ld1 {v20.4s, v21.4s}, [x8], #32
|
||||
ld1 {v23.4s, v24.4s}, [x9], #32
|
||||
ld1 {v26.4s, v27.4s}, [x3], #32
|
||||
b 2b
|
||||
|
||||
3:
|
||||
ldp d14, d15, [sp, #0x30]
|
||||
ldp d12, d13, [sp, #0x20]
|
||||
ldp d10, d11, [sp, #0x10]
|
||||
ldp d8, d9, [sp], 0x40
|
||||
ret
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_finish_weighted1_Xbpc_neon(pixel *dst,
|
||||
// const int32_t **a, const int16_t **b,
|
||||
// const int w, const int w1,
|
||||
// const int bitdepth_max);
|
||||
function sgr_finish_weighted1_\bpc\()bpc_neon, export=1
|
||||
ldp x7, x8, [x1]
|
||||
ldr x1, [x1, #16]
|
||||
ldp x9, x10, [x2]
|
||||
ldr x2, [x2, #16]
|
||||
|
||||
dup v31.8h, w4
|
||||
dup v30.8h, w5
|
||||
|
||||
movi v6.8h, #3
|
||||
movi v7.4s, #3
|
||||
1:
|
||||
ld1 {v0.8h, v1.8h}, [x9], #32
|
||||
ld1 {v2.8h, v3.8h}, [x10], #32
|
||||
ld1 {v4.8h, v5.8h}, [x2], #32
|
||||
ld1 {v16.4s, v17.4s, v18.4s}, [x7], #48
|
||||
ld1 {v19.4s, v20.4s, v21.4s}, [x8], #48
|
||||
ld1 {v22.4s, v23.4s, v24.4s}, [x1], #48
|
||||
|
||||
2:
|
||||
ext v25.16b, v0.16b, v1.16b, #2 // -stride
|
||||
ext v26.16b, v2.16b, v3.16b, #2 // 0
|
||||
ext v27.16b, v4.16b, v5.16b, #2 // +stride
|
||||
ext v28.16b, v0.16b, v1.16b, #4 // +1-stride
|
||||
ext v29.16b, v2.16b, v3.16b, #4 // +1
|
||||
add v2.8h, v2.8h, v25.8h // -1, -stride
|
||||
ext v25.16b, v4.16b, v5.16b, #4 // +1+stride
|
||||
add v26.8h, v26.8h, v27.8h // 0, +stride
|
||||
add v0.8h, v0.8h, v28.8h // -1-stride, +1-stride
|
||||
add v2.8h, v2.8h, v26.8h
|
||||
add v4.8h, v4.8h, v25.8h // -1+stride, +1+stride
|
||||
add v2.8h, v2.8h, v29.8h // +1
|
||||
add v0.8h, v0.8h, v4.8h
|
||||
|
||||
ext v25.16b, v16.16b, v17.16b, #4 // -stride
|
||||
ext v26.16b, v17.16b, v18.16b, #4
|
||||
shl v2.8h, v2.8h, #2
|
||||
ext v27.16b, v16.16b, v17.16b, #8 // +1-stride
|
||||
ext v28.16b, v17.16b, v18.16b, #8
|
||||
ext v29.16b, v19.16b, v20.16b, #4 // 0
|
||||
ext v4.16b, v20.16b, v21.16b, #4
|
||||
mla v2.8h, v0.8h, v6.8h // * 3 -> a
|
||||
add v25.4s, v25.4s, v19.4s // -stride, -1
|
||||
add v26.4s, v26.4s, v20.4s
|
||||
add v16.4s, v16.4s, v27.4s // -1-stride, +1-stride
|
||||
add v17.4s, v17.4s, v28.4s
|
||||
ext v27.16b, v19.16b, v20.16b, #8 // +1
|
||||
ext v28.16b, v20.16b, v21.16b, #8
|
||||
add v16.4s, v16.4s, v22.4s // -1+stride
|
||||
add v17.4s, v17.4s, v23.4s
|
||||
add v29.4s, v29.4s, v27.4s // 0, +1
|
||||
add v4.4s, v4.4s, v28.4s
|
||||
add v25.4s, v25.4s, v29.4s
|
||||
add v26.4s, v26.4s, v4.4s
|
||||
ext v27.16b, v22.16b, v23.16b, #4 // +stride
|
||||
ext v28.16b, v23.16b, v24.16b, #4
|
||||
ext v29.16b, v22.16b, v23.16b, #8 // +1+stride
|
||||
ext v4.16b, v23.16b, v24.16b, #8
|
||||
.if \bpc == 8
|
||||
ld1 {v19.8b}, [x0] // src
|
||||
.else
|
||||
ld1 {v19.8h}, [x0] // src
|
||||
.endif
|
||||
add v25.4s, v25.4s, v27.4s // +stride
|
||||
add v26.4s, v26.4s, v28.4s
|
||||
add v16.4s, v16.4s, v29.4s // +1+stride
|
||||
add v17.4s, v17.4s, v4.4s
|
||||
shl v25.4s, v25.4s, #2
|
||||
shl v26.4s, v26.4s, #2
|
||||
mla v25.4s, v16.4s, v7.4s // * 3 -> b
|
||||
mla v26.4s, v17.4s, v7.4s
|
||||
.if \bpc == 8
|
||||
uxtl v19.8h, v19.8b // src
|
||||
.endif
|
||||
mov v0.16b, v1.16b
|
||||
umlsl v25.4s, v2.4h, v19.4h // b - a * src
|
||||
umlsl2 v26.4s, v2.8h, v19.8h
|
||||
mov v2.16b, v3.16b
|
||||
rshrn v25.4h, v25.4s, #9
|
||||
rshrn2 v25.8h, v26.4s, #9
|
||||
|
||||
subs w3, w3, #8
|
||||
|
||||
// weighted1
|
||||
mov v4.16b, v5.16b
|
||||
|
||||
ld1 {v1.8h}, [x9], #16
|
||||
ld1 {v3.8h}, [x10], #16
|
||||
smull v26.4s, v25.4h, v31.4h // v = t1 * w1
|
||||
smull2 v27.4s, v25.8h, v31.8h
|
||||
ld1 {v5.8h}, [x2], #16
|
||||
rshrn v26.4h, v26.4s, #11
|
||||
rshrn2 v26.8h, v27.4s, #11
|
||||
usqadd v19.8h, v26.8h
|
||||
.if \bpc == 8
|
||||
mov v16.16b, v18.16b
|
||||
sqxtun v26.8b, v19.8h
|
||||
mov v19.16b, v21.16b
|
||||
mov v22.16b, v24.16b
|
||||
st1 {v26.8b}, [x0], #8
|
||||
.else
|
||||
mov v16.16b, v18.16b
|
||||
umin v26.8h, v19.8h, v30.8h
|
||||
mov v19.16b, v21.16b
|
||||
mov v22.16b, v24.16b
|
||||
st1 {v26.8h}, [x0], #16
|
||||
.endif
|
||||
|
||||
b.le 3f
|
||||
ld1 {v17.4s, v18.4s}, [x7], #32
|
||||
ld1 {v20.4s, v21.4s}, [x8], #32
|
||||
ld1 {v23.4s, v24.4s}, [x1], #32
|
||||
b 2b
|
||||
|
||||
3:
|
||||
ret
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_finish_filter2_2rows_Xbpc_neon(int16_t *tmp,
|
||||
// const pixel *src,
|
||||
// const ptrdiff_t stride,
|
||||
// const int32_t **a,
|
||||
// const int16_t **b,
|
||||
// const int w, const int h);
|
||||
function sgr_finish_filter2_2rows_\bpc\()bpc_neon, export=1
|
||||
stp d8, d9, [sp, #-0x40]!
|
||||
stp d10, d11, [sp, #0x10]
|
||||
stp d12, d13, [sp, #0x20]
|
||||
stp d14, d15, [sp, #0x30]
|
||||
|
||||
ldp x3, x7, [x3]
|
||||
ldp x4, x8, [x4]
|
||||
mov x10, #FILTER_OUT_STRIDE
|
||||
cmp w6, #1
|
||||
add x2, x1, x2 // src + stride
|
||||
csel x2, x1, x2, le // if (h <= 1) x2 = x1
|
||||
add x10, x0, x10, lsl #1
|
||||
movi v4.8h, #5
|
||||
movi v5.4s, #5
|
||||
movi v6.8h, #6
|
||||
movi v7.4s, #6
|
||||
1:
|
||||
ld1 {v0.8h, v1.8h}, [x4], #32
|
||||
ld1 {v2.8h, v3.8h}, [x8], #32
|
||||
ld1 {v16.4s, v17.4s, v18.4s}, [x3], #48
|
||||
ld1 {v19.4s, v20.4s, v21.4s}, [x7], #48
|
||||
|
||||
2:
|
||||
ext v24.16b, v0.16b, v1.16b, #4 // +1-stride
|
||||
ext v25.16b, v2.16b, v3.16b, #4 // +1+stride
|
||||
ext v22.16b, v0.16b, v1.16b, #2 // -stride
|
||||
ext v23.16b, v2.16b, v3.16b, #2 // +stride
|
||||
add v0.8h, v0.8h, v24.8h // -1-stride, +1-stride
|
||||
add v25.8h, v2.8h, v25.8h // -1+stride, +1+stride
|
||||
add v2.8h, v22.8h, v23.8h // -stride, +stride
|
||||
add v0.8h, v0.8h, v25.8h
|
||||
|
||||
mul v8.8h, v25.8h, v4.8h // * 5
|
||||
mla v8.8h, v23.8h, v6.8h // * 6
|
||||
|
||||
ext v22.16b, v16.16b, v17.16b, #4 // -stride
|
||||
ext v23.16b, v17.16b, v18.16b, #4
|
||||
ext v24.16b, v19.16b, v20.16b, #4 // +stride
|
||||
ext v25.16b, v20.16b, v21.16b, #4
|
||||
ext v26.16b, v16.16b, v17.16b, #8 // +1-stride
|
||||
ext v27.16b, v17.16b, v18.16b, #8
|
||||
ext v28.16b, v19.16b, v20.16b, #8 // +1+stride
|
||||
ext v29.16b, v20.16b, v21.16b, #8
|
||||
mul v0.8h, v0.8h, v4.8h // * 5
|
||||
mla v0.8h, v2.8h, v6.8h // * 6
|
||||
.if \bpc == 8
|
||||
ld1 {v31.8b}, [x1], #8
|
||||
ld1 {v30.8b}, [x2], #8
|
||||
.else
|
||||
ld1 {v31.8h}, [x1], #16
|
||||
ld1 {v30.8h}, [x2], #16
|
||||
.endif
|
||||
add v16.4s, v16.4s, v26.4s // -1-stride, +1-stride
|
||||
add v17.4s, v17.4s, v27.4s
|
||||
add v19.4s, v19.4s, v28.4s // -1+stride, +1+stride
|
||||
add v20.4s, v20.4s, v29.4s
|
||||
add v16.4s, v16.4s, v19.4s
|
||||
add v17.4s, v17.4s, v20.4s
|
||||
|
||||
mul v9.4s, v19.4s, v5.4s // * 5
|
||||
mla v9.4s, v24.4s, v7.4s // * 6
|
||||
mul v10.4s, v20.4s, v5.4s // * 5
|
||||
mla v10.4s, v25.4s, v7.4s // * 6
|
||||
|
||||
add v22.4s, v22.4s, v24.4s // -stride, +stride
|
||||
add v23.4s, v23.4s, v25.4s
|
||||
// This is, surprisingly, faster than other variants where the
|
||||
// mul+mla pairs are further apart, on Cortex A53.
|
||||
mul v16.4s, v16.4s, v5.4s // * 5
|
||||
mla v16.4s, v22.4s, v7.4s // * 6
|
||||
mul v17.4s, v17.4s, v5.4s // * 5
|
||||
mla v17.4s, v23.4s, v7.4s // * 6
|
||||
|
||||
.if \bpc == 8
|
||||
uxtl v31.8h, v31.8b
|
||||
uxtl v30.8h, v30.8b
|
||||
.endif
|
||||
umlsl v16.4s, v0.4h, v31.4h // b - a * src
|
||||
umlsl2 v17.4s, v0.8h, v31.8h
|
||||
umlsl v9.4s, v8.4h, v30.4h // b - a * src
|
||||
umlsl2 v10.4s, v8.8h, v30.8h
|
||||
mov v0.16b, v1.16b
|
||||
rshrn v16.4h, v16.4s, #9
|
||||
rshrn2 v16.8h, v17.4s, #9
|
||||
rshrn v9.4h, v9.4s, #8
|
||||
rshrn2 v9.8h, v10.4s, #8
|
||||
subs w5, w5, #8
|
||||
mov v2.16b, v3.16b
|
||||
st1 {v16.8h}, [x0], #16
|
||||
st1 {v9.8h}, [x10], #16
|
||||
|
||||
b.le 9f
|
||||
mov v16.16b, v18.16b
|
||||
mov v19.16b, v21.16b
|
||||
ld1 {v1.8h}, [x4], #16
|
||||
ld1 {v3.8h}, [x8], #16
|
||||
ld1 {v17.4s, v18.4s}, [x3], #32
|
||||
ld1 {v20.4s, v21.4s}, [x7], #32
|
||||
b 2b
|
||||
|
||||
9:
|
||||
ldp d14, d15, [sp, #0x30]
|
||||
ldp d12, d13, [sp, #0x20]
|
||||
ldp d10, d11, [sp, #0x10]
|
||||
ldp d8, d9, [sp], 0x40
|
||||
ret
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_finish_weighted2_Xbpc_neon(pixel *dst, const ptrdiff_t stride,
|
||||
// const int32_t **a,
|
||||
// const int16_t **b,
|
||||
// const int w, const int h,
|
||||
// const int w1,
|
||||
// const int bitdepth_max);
|
||||
function sgr_finish_weighted2_\bpc\()bpc_neon, export=1
|
||||
stp d8, d9, [sp, #-0x30]!
|
||||
str d10, [sp, #0x10]
|
||||
stp d14, d15, [sp, #0x20]
|
||||
|
||||
dup v14.8h, w6
|
||||
dup v15.8h, w7
|
||||
|
||||
ldp x2, x7, [x2]
|
||||
ldp x3, x8, [x3]
|
||||
cmp w5, #1
|
||||
add x1, x0, x1 // src + stride
|
||||
// if (h <= 1), set the pointer to the second row to any dummy buffer
|
||||
// we can clobber (x2 in this case)
|
||||
csel x1, x2, x1, le
|
||||
movi v4.8h, #5
|
||||
movi v5.4s, #5
|
||||
movi v6.8h, #6
|
||||
movi v7.4s, #6
|
||||
1:
|
||||
ld1 {v0.8h, v1.8h}, [x3], #32
|
||||
ld1 {v2.8h, v3.8h}, [x8], #32
|
||||
ld1 {v16.4s, v17.4s, v18.4s}, [x2], #48
|
||||
ld1 {v19.4s, v20.4s, v21.4s}, [x7], #48
|
||||
|
||||
2:
|
||||
ext v24.16b, v0.16b, v1.16b, #4 // +1-stride
|
||||
ext v25.16b, v2.16b, v3.16b, #4 // +1+stride
|
||||
ext v22.16b, v0.16b, v1.16b, #2 // -stride
|
||||
ext v23.16b, v2.16b, v3.16b, #2 // +stride
|
||||
add v0.8h, v0.8h, v24.8h // -1-stride, +1-stride
|
||||
add v25.8h, v2.8h, v25.8h // -1+stride, +1+stride
|
||||
add v2.8h, v22.8h, v23.8h // -stride, +stride
|
||||
add v0.8h, v0.8h, v25.8h
|
||||
|
||||
mul v8.8h, v25.8h, v4.8h // * 5
|
||||
mla v8.8h, v23.8h, v6.8h // * 6
|
||||
|
||||
ext v22.16b, v16.16b, v17.16b, #4 // -stride
|
||||
ext v23.16b, v17.16b, v18.16b, #4
|
||||
ext v24.16b, v19.16b, v20.16b, #4 // +stride
|
||||
ext v25.16b, v20.16b, v21.16b, #4
|
||||
ext v26.16b, v16.16b, v17.16b, #8 // +1-stride
|
||||
ext v27.16b, v17.16b, v18.16b, #8
|
||||
ext v28.16b, v19.16b, v20.16b, #8 // +1+stride
|
||||
ext v29.16b, v20.16b, v21.16b, #8
|
||||
mul v0.8h, v0.8h, v4.8h // * 5
|
||||
mla v0.8h, v2.8h, v6.8h // * 6
|
||||
.if \bpc == 8
|
||||
ld1 {v31.8b}, [x0]
|
||||
ld1 {v30.8b}, [x1]
|
||||
.else
|
||||
ld1 {v31.8h}, [x0]
|
||||
ld1 {v30.8h}, [x1]
|
||||
.endif
|
||||
add v16.4s, v16.4s, v26.4s // -1-stride, +1-stride
|
||||
add v17.4s, v17.4s, v27.4s
|
||||
add v19.4s, v19.4s, v28.4s // -1+stride, +1+stride
|
||||
add v20.4s, v20.4s, v29.4s
|
||||
add v16.4s, v16.4s, v19.4s
|
||||
add v17.4s, v17.4s, v20.4s
|
||||
|
||||
mul v9.4s, v19.4s, v5.4s // * 5
|
||||
mla v9.4s, v24.4s, v7.4s // * 6
|
||||
mul v10.4s, v20.4s, v5.4s // * 5
|
||||
mla v10.4s, v25.4s, v7.4s // * 6
|
||||
|
||||
add v22.4s, v22.4s, v24.4s // -stride, +stride
|
||||
add v23.4s, v23.4s, v25.4s
|
||||
// This is, surprisingly, faster than other variants where the
|
||||
// mul+mla pairs are further apart, on Cortex A53.
|
||||
mul v16.4s, v16.4s, v5.4s // * 5
|
||||
mla v16.4s, v22.4s, v7.4s // * 6
|
||||
mul v17.4s, v17.4s, v5.4s // * 5
|
||||
mla v17.4s, v23.4s, v7.4s // * 6
|
||||
|
||||
.if \bpc == 8
|
||||
uxtl v31.8h, v31.8b
|
||||
uxtl v30.8h, v30.8b
|
||||
.endif
|
||||
umlsl v16.4s, v0.4h, v31.4h // b - a * src
|
||||
umlsl2 v17.4s, v0.8h, v31.8h
|
||||
umlsl v9.4s, v8.4h, v30.4h // b - a * src
|
||||
umlsl2 v10.4s, v8.8h, v30.8h
|
||||
mov v0.16b, v1.16b
|
||||
rshrn v16.4h, v16.4s, #9
|
||||
rshrn2 v16.8h, v17.4s, #9
|
||||
rshrn v9.4h, v9.4s, #8
|
||||
rshrn2 v9.8h, v10.4s, #8
|
||||
|
||||
subs w4, w4, #8
|
||||
|
||||
// weighted1
|
||||
mov v2.16b, v3.16b
|
||||
|
||||
ld1 {v1.8h}, [x3], #16
|
||||
ld1 {v3.8h}, [x8], #16
|
||||
smull v22.4s, v16.4h, v14.4h // v
|
||||
smull2 v23.4s, v16.8h, v14.8h
|
||||
mov v16.16b, v18.16b
|
||||
smull v24.4s, v9.4h, v14.4h
|
||||
smull2 v25.4s, v9.8h, v14.8h
|
||||
mov v19.16b, v21.16b
|
||||
rshrn v22.4h, v22.4s, #11
|
||||
rshrn2 v22.8h, v23.4s, #11
|
||||
rshrn v23.4h, v24.4s, #11
|
||||
rshrn2 v23.8h, v25.4s, #11
|
||||
usqadd v31.8h, v22.8h
|
||||
usqadd v30.8h, v23.8h
|
||||
.if \bpc == 8
|
||||
sqxtun v22.8b, v31.8h
|
||||
sqxtun v23.8b, v30.8h
|
||||
st1 {v22.8b}, [x0], #8
|
||||
st1 {v23.8b}, [x1], #8
|
||||
.else
|
||||
umin v22.8h, v31.8h, v15.8h
|
||||
umin v23.8h, v30.8h, v15.8h
|
||||
st1 {v22.8h}, [x0], #16
|
||||
st1 {v23.8h}, [x1], #16
|
||||
.endif
|
||||
|
||||
b.le 3f
|
||||
ld1 {v17.4s, v18.4s}, [x2], #32
|
||||
ld1 {v20.4s, v21.4s}, [x7], #32
|
||||
b 2b
|
||||
|
||||
3:
|
||||
ldp d14, d15, [sp, #0x20]
|
||||
ldr d10, [sp, #0x10]
|
||||
ldp d8, d9, [sp], 0x30
|
||||
ret
|
||||
endfunc
|
||||
|
||||
// void dav1d_sgr_weighted2_Xbpc_neon(pixel *dst, const ptrdiff_t stride,
|
||||
// const int16_t *t1, const int16_t *t2,
|
||||
// const int w, const int h,
|
||||
// const int16_t wt[2], const int bitdepth_max);
|
||||
function sgr_weighted2_\bpc\()bpc_neon, export=1
|
||||
cmp w5, #2
|
||||
add x10, x0, x1
|
||||
add x12, x2, #2*FILTER_OUT_STRIDE
|
||||
add x13, x3, #2*FILTER_OUT_STRIDE
|
||||
ld2r {v30.8h, v31.8h}, [x6] // wt[0], wt[1]
|
||||
.if \bpc == 16
|
||||
dup v29.8h, w7
|
||||
.endif
|
||||
mov x8, #4*FILTER_OUT_STRIDE
|
||||
lsl x1, x1, #1
|
||||
add w9, w4, #7
|
||||
bic x9, x9, #7 // Aligned width
|
||||
.if \bpc == 8
|
||||
sub x1, x1, x9
|
||||
.else
|
||||
sub x1, x1, x9, lsl #1
|
||||
.endif
|
||||
sub x8, x8, x9, lsl #1
|
||||
mov w9, w4
|
||||
b.lt 2f
|
||||
1:
|
||||
.if \bpc == 8
|
||||
ld1 {v0.8b}, [x0]
|
||||
ld1 {v16.8b}, [x10]
|
||||
.else
|
||||
ld1 {v0.8h}, [x0]
|
||||
ld1 {v16.8h}, [x10]
|
||||
.endif
|
||||
ld1 {v1.8h}, [x2], #16
|
||||
ld1 {v17.8h}, [x12], #16
|
||||
ld1 {v2.8h}, [x3], #16
|
||||
ld1 {v18.8h}, [x13], #16
|
||||
subs w4, w4, #8
|
||||
.if \bpc == 8
|
||||
uxtl v0.8h, v0.8b
|
||||
uxtl v16.8h, v16.8b
|
||||
.endif
|
||||
smull v3.4s, v1.4h, v30.4h // wt[0] * t1
|
||||
smlal v3.4s, v2.4h, v31.4h // wt[1] * t2
|
||||
smull2 v4.4s, v1.8h, v30.8h // wt[0] * t1
|
||||
smlal2 v4.4s, v2.8h, v31.8h // wt[1] * t2
|
||||
smull v19.4s, v17.4h, v30.4h // wt[0] * t1
|
||||
smlal v19.4s, v18.4h, v31.4h // wt[1] * t2
|
||||
smull2 v20.4s, v17.8h, v30.8h // wt[0] * t1
|
||||
smlal2 v20.4s, v18.8h, v31.8h // wt[1] * t2
|
||||
rshrn v3.4h, v3.4s, #11
|
||||
rshrn2 v3.8h, v4.4s, #11
|
||||
rshrn v19.4h, v19.4s, #11
|
||||
rshrn2 v19.8h, v20.4s, #11
|
||||
usqadd v0.8h, v3.8h
|
||||
usqadd v16.8h, v19.8h
|
||||
.if \bpc == 8
|
||||
sqxtun v3.8b, v0.8h
|
||||
sqxtun v19.8b, v16.8h
|
||||
st1 {v3.8b}, [x0], #8
|
||||
st1 {v19.8b}, [x10], #8
|
||||
.else
|
||||
umin v3.8h, v0.8h, v29.8h
|
||||
umin v19.8h, v16.8h, v29.8h
|
||||
st1 {v3.8h}, [x0], #16
|
||||
st1 {v19.8h}, [x10], #16
|
||||
.endif
|
||||
b.gt 1b
|
||||
|
||||
subs w5, w5, #2
|
||||
cmp w5, #1
|
||||
b.lt 0f
|
||||
mov w4, w9
|
||||
add x0, x0, x1
|
||||
add x10, x10, x1
|
||||
add x2, x2, x8
|
||||
add x12, x12, x8
|
||||
add x3, x3, x8
|
||||
add x13, x13, x8
|
||||
b.eq 2f
|
||||
b 1b
|
||||
|
||||
2:
|
||||
.if \bpc == 8
|
||||
ld1 {v0.8b}, [x0]
|
||||
.else
|
||||
ld1 {v0.8h}, [x0]
|
||||
.endif
|
||||
ld1 {v1.8h}, [x2], #16
|
||||
ld1 {v2.8h}, [x3], #16
|
||||
subs w4, w4, #8
|
||||
.if \bpc == 8
|
||||
uxtl v0.8h, v0.8b
|
||||
.endif
|
||||
smull v3.4s, v1.4h, v30.4h // wt[0] * t1
|
||||
smlal v3.4s, v2.4h, v31.4h // wt[1] * t2
|
||||
smull2 v4.4s, v1.8h, v30.8h // wt[0] * t1
|
||||
smlal2 v4.4s, v2.8h, v31.8h // wt[1] * t2
|
||||
rshrn v3.4h, v3.4s, #11
|
||||
rshrn2 v3.8h, v4.4s, #11
|
||||
usqadd v0.8h, v3.8h
|
||||
.if \bpc == 8
|
||||
sqxtun v3.8b, v0.8h
|
||||
st1 {v3.8b}, [x0], #8
|
||||
.else
|
||||
umin v3.8h, v0.8h, v29.8h
|
||||
st1 {v3.8h}, [x0], #16
|
||||
.endif
|
||||
b.gt 2b
|
||||
0:
|
||||
ret
|
||||
endfunc
|
||||
.endm
|
||||
3574
media/libdav1d/src/src/arm/64/mc.S
Normal file
3574
media/libdav1d/src/src/arm/64/mc.S
Normal file
File diff suppressed because it is too large
Load diff
3833
media/libdav1d/src/src/arm/64/mc16.S
Normal file
3833
media/libdav1d/src/src/arm/64/mc16.S
Normal file
File diff suppressed because it is too large
Load diff
1649
media/libdav1d/src/src/arm/64/mc16_sve.S
Normal file
1649
media/libdav1d/src/src/arm/64/mc16_sve.S
Normal file
File diff suppressed because it is too large
Load diff
1880
media/libdav1d/src/src/arm/64/mc_dotprod.S
Normal file
1880
media/libdav1d/src/src/arm/64/mc_dotprod.S
Normal file
File diff suppressed because it is too large
Load diff
595
media/libdav1d/src/src/arm/64/msac.S
Normal file
595
media/libdav1d/src/src/arm/64/msac.S
Normal file
|
|
@ -0,0 +1,595 @@
|
|||
/*
|
||||
* Copyright © 2019, VideoLAN and dav1d authors
|
||||
* Copyright © 2019, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
#define BUF_POS 0
|
||||
#define BUF_END 8
|
||||
#define DIF 16
|
||||
#define RNG 24
|
||||
#define CNT 28
|
||||
#define ALLOW_UPDATE_CDF 32
|
||||
|
||||
#define COEFFS_BASE_OFFSET 30
|
||||
#define MASKS8_OFFSET (64-COEFFS_BASE_OFFSET)
|
||||
|
||||
const coeffs
|
||||
.short 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0
|
||||
.short 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
// masks8
|
||||
.short -0x202, -0x202, -0x202, -0x202, -0x202, -0x202, -0x202, 0xF0E
|
||||
endconst
|
||||
|
||||
.macro ld1_n d0, d1, src, sz, n
|
||||
.if \n <= 8
|
||||
ld1 {\d0\sz}, [\src]
|
||||
.else
|
||||
ld1 {\d0\sz, \d1\sz}, [\src]
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro st1_n s0, s1, dst, sz, n
|
||||
.if \n <= 8
|
||||
st1 {\s0\sz}, [\dst]
|
||||
.else
|
||||
st1 {\s0\sz, \s1\sz}, [\dst]
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro ushr_n d0, d1, s0, s1, shift, sz, n
|
||||
ushr \d0\sz, \s0\sz, \shift
|
||||
.if \n == 16
|
||||
ushr \d1\sz, \s1\sz, \shift
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro add_n d0, d1, s0, s1, s2, s3, sz, n
|
||||
add \d0\sz, \s0\sz, \s2\sz
|
||||
.if \n == 16
|
||||
add \d1\sz, \s1\sz, \s3\sz
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro sub_n d0, d1, s0, s1, s2, s3, sz, n
|
||||
sub \d0\sz, \s0\sz, \s2\sz
|
||||
.if \n == 16
|
||||
sub \d1\sz, \s1\sz, \s3\sz
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro and_n d0, d1, s0, s1, s2, s3, sz, n
|
||||
and \d0\sz, \s0\sz, \s2\sz
|
||||
.if \n == 16
|
||||
and \d1\sz, \s1\sz, \s3\sz
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro cmhs_n d0, d1, s0, s1, s2, s3, sz, n
|
||||
cmhs \d0\sz, \s0\sz, \s2\sz
|
||||
.if \n == 16
|
||||
cmhs \d1\sz, \s1\sz, \s3\sz
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro sshl_n d0, d1, s0, s1, s2, s3, sz, n
|
||||
sshl \d0\sz, \s0\sz, \s2\sz
|
||||
.if \n == 16
|
||||
sshl \d1\sz, \s1\sz, \s3\sz
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro sqdmulh_n d0, d1, s0, s1, s2, s3, sz, n
|
||||
sqdmulh \d0\sz, \s0\sz, \s2\sz
|
||||
.if \n == 16
|
||||
sqdmulh \d1\sz, \s1\sz, \s3\sz
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro str_n idx0, idx1, dstreg, dstoff, n
|
||||
str \idx0, [\dstreg, \dstoff]
|
||||
.if \n == 16
|
||||
str \idx1, [\dstreg, \dstoff + 16]
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// unsigned dav1d_msac_decode_symbol_adapt4_neon(MsacContext *s, uint16_t *cdf,
|
||||
// size_t n_symbols);
|
||||
|
||||
function msac_decode_symbol_adapt4_neon, export=1
|
||||
.macro decode_update sz, szb, n
|
||||
.if \n == 16
|
||||
sub sp, sp, #48
|
||||
.endif
|
||||
add x8, x0, #RNG
|
||||
ld1_n v0, v1, x1, \sz, \n // cdf
|
||||
ld1r {v29\sz}, [x8] // rng
|
||||
movrel x9, coeffs, COEFFS_BASE_OFFSET
|
||||
movi v31\sz, #0x7f, lsl #8 // 0x7f00
|
||||
sub x10, x9, x2, lsl #1
|
||||
mvni v30\sz, #0x3f // 0xffc0
|
||||
and v7\szb, v29\szb, v31\szb // rng & 0x7f00
|
||||
.if \n == 16
|
||||
str h29, [sp, #14] // store original u = s->rng
|
||||
.endif
|
||||
and_n v2, v3, v0, v1, v30, v30, \szb, \n // cdf & 0xffc0
|
||||
|
||||
ld1_n v4, v5, x10, \sz, \n // EC_MIN_PROB * (n_symbols - ret)
|
||||
sqdmulh_n v6, v7, v2, v3, v7, v7, \sz, \n // ((cdf >> EC_PROB_SHIFT) * (r - 128)) >> 1
|
||||
ldr d28, [x0, #DIF]
|
||||
|
||||
add_n v4, v5, v2, v3, v4, v5, \sz, \n // v = cdf + EC_MIN_PROB * (n_symbols - ret)
|
||||
add_n v4, v5, v6, v7, v4, v5, \sz, \n // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret)
|
||||
|
||||
dup v30\sz, v28.h[3] // dif >> (EC_WIN_SIZE - 16)
|
||||
.if \n == 8
|
||||
ldur q31, [x9, #MASKS8_OFFSET]
|
||||
.elseif \n == 16
|
||||
str_n q4, q5, sp, #16, \n // store v values to allow indexed access
|
||||
.endif
|
||||
|
||||
// After the condition starts being true it continues, such that the vector looks like:
|
||||
// 0, 0, 0 ... -1, -1
|
||||
cmhs_n v2, v3, v30, v30, v4, v5, \sz, \n // c >= v
|
||||
.if \n == 4
|
||||
ext v29\szb, v29\szb, v4\szb, #6 // u
|
||||
umov x15, v2.d[0]
|
||||
ldr w4, [x0, #ALLOW_UPDATE_CDF]
|
||||
rev x15, x15
|
||||
sub v29\sz, v29\sz, v4\sz // rng = u-v
|
||||
// rev + clz = count trailing zeros
|
||||
clz x15, x15 // 16*ret
|
||||
.elseif \n == 8
|
||||
// The final short of the compare is always set.
|
||||
// Using addv, subtract -0x202*ret from this value to create a lookup table for a short.
|
||||
// For n == 8:
|
||||
// -0x202 + -0x202 + ... + 0xF0E
|
||||
// (0x202*7) | (1 << 8)
|
||||
// ^-------offset for second byte of the short
|
||||
and v31\szb, v31\szb, v2\szb
|
||||
ext v29\szb, v29\szb, v4\szb, #14 // u
|
||||
addv h31, v31\sz // ((2*ret + 1) << 8) | (2*ret)
|
||||
ldr w4, [x0, #ALLOW_UPDATE_CDF]
|
||||
sub v30\sz, v30\sz, v4\sz // (dif >> 48) - v
|
||||
smov w15, v31.b[0] // 2*ret
|
||||
sub v29\sz, v29\sz, v4\sz // rng = u-v
|
||||
.elseif \n == 16
|
||||
add v6\sz, v2\sz, v3\sz
|
||||
addv h31, v6\sz // -n + ret
|
||||
ldr w4, [x0, #ALLOW_UPDATE_CDF]
|
||||
smov w15, v31.h[0]
|
||||
.endif
|
||||
|
||||
cbz w4, 0f
|
||||
|
||||
// update_cdf
|
||||
ldrh w3, [x1, x2, lsl #1] // count = cdf[n_symbols]
|
||||
.if \n == 16
|
||||
// 16 case has a lower bound that guarantees n_symbols > 2
|
||||
mov w4, #-5
|
||||
.elseif \n == 8
|
||||
mvn w14, w2
|
||||
mov w4, #-4
|
||||
cmn w14, #3 // set C if n_symbols <= 2
|
||||
.else
|
||||
// if n_symbols < 4 (or < 6 even) then
|
||||
// (1 + n_symbols) >> 2 == n_symbols > 2
|
||||
add w14, w2, #17 // (1 + n_symbols) + (4 << 2)
|
||||
.endif
|
||||
sub_n v16, v17, v0, v1, v2, v3, \sz, \n // cdf + (i >= val ? 1 : 0)
|
||||
orr v2\sz, #0x80, lsl #8
|
||||
.if \n == 16
|
||||
orr v3\sz, #0x80, lsl #8
|
||||
.endif
|
||||
.if \n == 16
|
||||
sub w4, w4, w3, lsr #4 // -((count >> 4) + 5)
|
||||
.elseif \n == 8
|
||||
lsr w14, w3, #4 // count >> 4
|
||||
sbc w4, w4, w14 // -((count >> 4) + (n_symbols > 2) + 4)
|
||||
.else
|
||||
neg w4, w14, lsr #2 // -((n_symbols > 2) + 4)
|
||||
sub w4, w4, w3, lsr #4 // -((count >> 4) + (n_symbols > 2) + 4)
|
||||
.endif
|
||||
sub_n v2, v3, v2, v3, v0, v1, \sz, \n // (32768 - cdf[i]) or (-1 - cdf[i])
|
||||
dup v6\sz, w4 // -rate
|
||||
|
||||
sub w3, w3, w3, lsr #5 // count - (count == 32)
|
||||
sshl_n v2, v3, v2, v3, v6, v6, \sz, \n // ({32768,-1} - cdf[i]) >> rate
|
||||
add w3, w3, #1 // count + (count < 32)
|
||||
add_n v0, v1, v16, v17, v2, v3, \sz, \n // cdf + (32768 - cdf[i]) >> rate
|
||||
st1_n v0, v1, x1, \sz, \n
|
||||
strh w3, [x1, x2, lsl #1]
|
||||
|
||||
0:
|
||||
// renorm
|
||||
.if \n == 4
|
||||
ldr w6, [x0, #CNT]
|
||||
ldr x7, [x0, #DIF]
|
||||
mov x4, v29.d[0] // rng (packed)
|
||||
mov x3, v4.d[0] // v (packed)
|
||||
|
||||
// Shift 'v'/'rng' for ret into the 16 least sig bits. There is
|
||||
// garbage in the remaining bits, but we can work around this.
|
||||
lsr x4, x4, x15 // rng
|
||||
lsr x3, x3, x15 // v
|
||||
lsl w5, w4, #16 // rng << 16
|
||||
sub x7, x7, x3, lsl #48 // dif - (v << 48)
|
||||
clz w5, w5 // d = clz(rng << 16)
|
||||
lsl w4, w4, w5 // rng << d
|
||||
subs w6, w6, w5 // cnt -= d
|
||||
lsl x7, x7, x5 // (dif - (v << 48)) << d
|
||||
strh w4, [x0, #RNG]
|
||||
b.lo 1f
|
||||
str w6, [x0, #CNT]
|
||||
str x7, [x0, #DIF]
|
||||
lsr w0, w15, #4
|
||||
ret
|
||||
1:
|
||||
lsr w15, w15, #4
|
||||
b L(refill)
|
||||
.elseif \n == 8
|
||||
ldr w6, [x0, #CNT]
|
||||
tbl v30.8b, {v30.16b}, v31.8b
|
||||
tbl v29.8b, {v29.16b}, v31.8b
|
||||
ins v28.h[3], v30.h[0] // dif - (v << 48)
|
||||
clz v0.4h, v29.4h // d = clz(rng)
|
||||
umov w5, v0.h[0]
|
||||
ushl v29.4h, v29.4h, v0.4h // rng << d
|
||||
|
||||
// The vec for clz(rng) is filled with garbage after the first short,
|
||||
// but ushl/sshl conveniently uses only the first byte for the shift
|
||||
// amount.
|
||||
ushl d28, d28, d0 // (dif - (v << 48)) << d
|
||||
|
||||
subs w6, w6, w5 // cnt -= d
|
||||
str h29, [x0, #RNG]
|
||||
b.lo 1f
|
||||
str w6, [x0, #CNT]
|
||||
str d28, [x0, #DIF]
|
||||
lsr w0, w15, #1 // ret
|
||||
ret
|
||||
1:
|
||||
lsr w15, w15, #1 // ret
|
||||
mov x7, v28.d[0]
|
||||
b L(refill)
|
||||
.elseif \n == 16
|
||||
add x8, sp, w15, sxtw #1
|
||||
ldrh w3, [x8, #48] // v
|
||||
ldurh w4, [x8, #46] // u
|
||||
ldr w6, [x0, #CNT]
|
||||
ldr x7, [x0, #DIF]
|
||||
sub w4, w4, w3 // rng = u - v
|
||||
clz w5, w4 // clz(rng)
|
||||
eor w5, w5, #16 // d = clz(rng) ^ 16
|
||||
sub x7, x7, x3, lsl #48 // dif - (v << 48)
|
||||
lsl w4, w4, w5 // rng << d
|
||||
subs w6, w6, w5 // cnt -= d
|
||||
lsl x7, x7, x5 // (dif - (v << 48)) << d
|
||||
str w4, [x0, #RNG]
|
||||
add sp, sp, #48
|
||||
b.lo 1f
|
||||
str w6, [x0, #CNT]
|
||||
str x7, [x0, #DIF]
|
||||
add w0, w15, #\n // ret
|
||||
ret
|
||||
1:
|
||||
add w15, w15, #\n // ret
|
||||
b L(refill)
|
||||
.endif
|
||||
.endm
|
||||
|
||||
decode_update .4h, .8b, 4
|
||||
|
||||
L(refill):
|
||||
// refill
|
||||
ldp x3, x4, [x0] // BUF_POS, BUF_END
|
||||
add x5, x3, #8
|
||||
subs x5, x5, x4
|
||||
b.hi 6f
|
||||
|
||||
ldr x8, [x3] // next_bits
|
||||
add w4, w6, #-48 // shift_bits = cnt + 16 (- 64)
|
||||
mvn x8, x8
|
||||
neg w5, w4
|
||||
rev x8, x8 // next_bits = bswap(next_bits)
|
||||
lsr w5, w5, #3 // num_bytes_read
|
||||
lsr x8, x8, x4 // next_bits >>= (shift_bits & 63)
|
||||
|
||||
2: // refill_end
|
||||
add x3, x3, x5
|
||||
add w6, w6, w5, lsl #3 // cnt += num_bits_read
|
||||
str x3, [x0, #BUF_POS]
|
||||
|
||||
3: // refill_end2
|
||||
orr x7, x7, x8 // dif |= next_bits
|
||||
|
||||
4: // end
|
||||
str w6, [x0, #CNT]
|
||||
str x7, [x0, #DIF]
|
||||
|
||||
mov w0, w15
|
||||
ret
|
||||
|
||||
5: // pad_with_ones
|
||||
add w8, w6, #-16
|
||||
ror x8, x8, x8
|
||||
b 3b
|
||||
|
||||
6: // refill_eob
|
||||
cmp x3, x4
|
||||
b.hs 5b
|
||||
|
||||
ldr x8, [x4, #-8]
|
||||
lsl w5, w5, #3
|
||||
lsr x8, x8, x5
|
||||
add w5, w6, #-48
|
||||
mvn x8, x8
|
||||
sub w4, w4, w3 // num_bytes_left
|
||||
rev x8, x8
|
||||
lsr x8, x8, x5
|
||||
neg w5, w5
|
||||
lsr w5, w5, #3
|
||||
cmp w5, w4
|
||||
csel w5, w5, w4, lo // num_bytes_read
|
||||
b 2b
|
||||
endfunc
|
||||
|
||||
function msac_decode_symbol_adapt8_neon, export=1
|
||||
decode_update .8h, .16b, 8
|
||||
endfunc
|
||||
|
||||
function msac_decode_symbol_adapt16_neon, export=1
|
||||
decode_update .8h, .16b, 16
|
||||
endfunc
|
||||
|
||||
function msac_decode_hi_tok_neon, export=1
|
||||
ld1 {v0.4h}, [x1] // cdf
|
||||
add x16, x0, #RNG
|
||||
movi v31.4h, #0x7f, lsl #8 // 0x7f00
|
||||
movrel x17, coeffs, COEFFS_BASE_OFFSET-2*3
|
||||
mvni v30.4h, #0x3f // 0xffc0
|
||||
ldrh w9, [x1, #6] // count = cdf[n_symbols]
|
||||
ld1r {v3.4h}, [x16] // rng
|
||||
ld1 {v29.4h}, [x17] // EC_MIN_PROB * (n_symbols - ret)
|
||||
add x17, x0, #DIF + 6
|
||||
mov w13, #-24*8
|
||||
and v17.8b, v0.8b, v30.8b // cdf & 0xffc0
|
||||
ldr w10, [x0, #ALLOW_UPDATE_CDF]
|
||||
ld1r {v1.8h}, [x17] // dif >> (EC_WIN_SIZE - 16)
|
||||
ldr w6, [x0, #CNT]
|
||||
ldr x7, [x0, #DIF]
|
||||
1:
|
||||
and v7.8b, v3.8b, v31.8b // rng & 0x7f00
|
||||
sqdmulh v6.4h, v17.4h, v7.4h // ((cdf >> EC_PROB_SHIFT) * (r - 128)) >> 1
|
||||
add v4.4h, v17.4h, v29.4h // v = cdf + EC_MIN_PROB * (n_symbols - ret)
|
||||
add v4.4h, v6.4h, v4.4h // v = ((cdf >> EC_PROB_SHIFT) * r) >> 1 + EC_MIN_PROB * (n_symbols - ret)
|
||||
cmhs v2.4h, v1.4h, v4.4h // c >= v
|
||||
add w13, w13, #5*8
|
||||
ext v18.8b, v3.8b, v4.8b, #6 // u
|
||||
umov x15, v2.d[0]
|
||||
rev x15, x15
|
||||
sub v18.4h, v18.4h, v4.4h // rng = u-v
|
||||
// rev + clz = count trailing zeros
|
||||
clz x15, x15 // 16*ret
|
||||
|
||||
cbz w10, 2f
|
||||
// update_cdf
|
||||
sub v5.4h, v0.4h, v2.4h // cdf[i] + (i >= val ? 1 : 0)
|
||||
mov w4, #-5
|
||||
orr v2.4h, #0x80, lsl #8 // i >= val ? -1 : 32768
|
||||
sub w4, w4, w9, lsr #4 // -((count >> 4) + 5)
|
||||
sub v2.4h, v2.4h, v0.4h // (32768 - cdf[i]) or (-1 - cdf[i])
|
||||
dup v6.4h, w4 // -rate
|
||||
|
||||
sub w9, w9, w9, lsr #5 // count - (count == 32)
|
||||
sshl v2.4h, v2.4h, v6.4h // ({32768,-1} - cdf[i]) >> rate
|
||||
add w9, w9, #1 // count + (count < 32)
|
||||
add v0.4h, v5.4h, v2.4h // cdf[i] + (32768 - cdf[i]) >> rate
|
||||
st1 {v0.4h}, [x1]
|
||||
and v17.8b, v0.8b, v30.8b // cdf & 0xffc0
|
||||
strh w9, [x1, #6]
|
||||
|
||||
2:
|
||||
mov x4, v18.d[0] // rng (packed)
|
||||
mov x3, v4.d[0] // v (packed)
|
||||
|
||||
// Shift 'v'/'rng' for ret into the 16 least sig bits. There is
|
||||
// garbage in the remaining bits, but we can work around this.
|
||||
lsr x4, x4, x15 // rng
|
||||
lsr x3, x3, x15 // v
|
||||
lsl w5, w4, #16 // rng << 16
|
||||
sub x7, x7, x3, lsl #48 // dif - (v << 48)
|
||||
clz w5, w5 // d = clz(rng << 16)
|
||||
lsl w4, w4, w5 // rng << d
|
||||
subs w6, w6, w5 // cnt -= d
|
||||
lsl x7, x7, x5 // (dif - (v << 48)) << d
|
||||
strh w4, [x0, #RNG]
|
||||
dup v3.4h, w4
|
||||
b.hs 5f
|
||||
|
||||
// refill
|
||||
ldp x3, x4, [x0] // BUF_POS, BUF_END
|
||||
add x5, x3, #8
|
||||
subs x5, x5, x4
|
||||
b.hi 7f
|
||||
|
||||
ldr x8, [x3] // next_bits
|
||||
add w4, w6, #-48 // shift_bits = cnt + 16 (- 64)
|
||||
mvn x8, x8
|
||||
neg w5, w4
|
||||
rev x8, x8 // next_bits = bswap(next_bits)
|
||||
lsr w5, w5, #3 // num_bytes_read
|
||||
lsr x8, x8, x4 // next_bits >>= (shift_bits & 63)
|
||||
|
||||
3: // refill_end
|
||||
add x3, x3, x5
|
||||
add w6, w6, w5, lsl #3 // cnt += num_bits_read
|
||||
str x3, [x0, #BUF_POS]
|
||||
|
||||
4: // refill_end2
|
||||
orr x7, x7, x8 // dif |= next_bits
|
||||
|
||||
5: // end
|
||||
sub w15, w15, #5*8
|
||||
lsr x12, x7, #48
|
||||
adds w13, w13, w15 // carry = tok_br < 3 || tok == 15
|
||||
dup v1.8h, w12
|
||||
b.cc 1b // loop if !carry
|
||||
add w13, w13, #30*8
|
||||
str w6, [x0, #CNT]
|
||||
str x7, [x0, #DIF]
|
||||
lsr w0, w13, #4
|
||||
ret
|
||||
|
||||
6: // pad_with_ones
|
||||
add w8, w6, #-16
|
||||
ror x8, x8, x8
|
||||
b 4b
|
||||
|
||||
7: // refill_eob
|
||||
cmp x3, x4
|
||||
b.hs 6b
|
||||
|
||||
ldr x8, [x4, #-8]
|
||||
lsl w5, w5, #3
|
||||
lsr x8, x8, x5
|
||||
add w5, w6, #-48
|
||||
mvn x8, x8
|
||||
sub w4, w4, w3 // num_bytes_left
|
||||
rev x8, x8
|
||||
lsr x8, x8, x5
|
||||
neg w5, w5
|
||||
lsr w5, w5, #3
|
||||
cmp w5, w4
|
||||
csel w5, w5, w4, lo // num_bytes_read
|
||||
b 3b
|
||||
endfunc
|
||||
|
||||
function msac_decode_bool_equi_neon, export=1
|
||||
ldp w5, w6, [x0, #RNG] // + CNT
|
||||
ldr x7, [x0, #DIF]
|
||||
bic w4, w5, #0xff // r &= 0xff00
|
||||
add w4, w4, #8
|
||||
subs x8, x7, x4, lsl #47 // dif - vw
|
||||
lsr w4, w4, #1 // v
|
||||
sub w5, w5, w4 // r - v
|
||||
cset w15, lo
|
||||
csel w4, w5, w4, hs // if (ret) v = r - v;
|
||||
csel x7, x8, x7, hs // if (ret) dif = dif - vw;
|
||||
|
||||
clz w5, w4 // clz(rng)
|
||||
eor w5, w5, #16 // d = clz(rng) ^ 16
|
||||
lsl w4, w4, w5 // rng << d
|
||||
subs w6, w6, w5 // cnt -= d
|
||||
lsl x7, x7, x5 // (dif - (v << 48)) << d
|
||||
str w4, [x0, #RNG]
|
||||
b.lo L(refill)
|
||||
|
||||
str w6, [x0, #CNT]
|
||||
str x7, [x0, #DIF]
|
||||
mov w0, w15
|
||||
ret
|
||||
endfunc
|
||||
|
||||
function msac_decode_bool_neon, export=1
|
||||
ldp w5, w6, [x0, #RNG] // + CNT
|
||||
ldr x7, [x0, #DIF]
|
||||
lsr w4, w5, #8 // r >> 8
|
||||
bic w1, w1, #0x3f // f &= ~63
|
||||
mul w4, w4, w1
|
||||
lsr w4, w4, #7
|
||||
add w4, w4, #4 // v
|
||||
subs x8, x7, x4, lsl #48 // dif - vw
|
||||
sub w5, w5, w4 // r - v
|
||||
cset w15, lo
|
||||
csel w4, w5, w4, hs // if (ret) v = r - v;
|
||||
csel x7, x8, x7, hs // if (ret) dif = dif - vw;
|
||||
|
||||
clz w5, w4 // clz(rng)
|
||||
eor w5, w5, #16 // d = clz(rng) ^ 16
|
||||
lsl w4, w4, w5 // rng << d
|
||||
subs w6, w6, w5 // cnt -= d
|
||||
lsl x7, x7, x5 // (dif - (v << 48)) << d
|
||||
str w4, [x0, #RNG]
|
||||
b.lo L(refill)
|
||||
|
||||
str w6, [x0, #CNT]
|
||||
str x7, [x0, #DIF]
|
||||
mov w0, w15
|
||||
ret
|
||||
endfunc
|
||||
|
||||
function msac_decode_bool_adapt_neon, export=1
|
||||
ldr w9, [x1] // cdf[0-1]
|
||||
ldp w5, w6, [x0, #RNG] // + CNT
|
||||
ldr x7, [x0, #DIF]
|
||||
lsr w4, w5, #8 // r >> 8
|
||||
and w2, w9, #0xffc0 // f &= ~63
|
||||
mul w4, w4, w2
|
||||
lsr w4, w4, #7
|
||||
add w4, w4, #4 // v
|
||||
subs x8, x7, x4, lsl #48 // dif - vw
|
||||
sub w5, w5, w4 // r - v
|
||||
cset w15, lo
|
||||
csel w4, w5, w4, hs // if (ret) v = r - v;
|
||||
csel x7, x8, x7, hs // if (ret) dif = dif - vw;
|
||||
|
||||
ldr w10, [x0, #ALLOW_UPDATE_CDF]
|
||||
|
||||
clz w5, w4 // clz(rng)
|
||||
eor w5, w5, #16 // d = clz(rng) ^ 16
|
||||
|
||||
cbz w10, 1f
|
||||
|
||||
lsr w2, w9, #16 // count = cdf[1]
|
||||
and w9, w9, #0xffff // cdf[0]
|
||||
|
||||
sub w3, w2, w2, lsr #5 // count - (count >= 32)
|
||||
lsr w2, w2, #4 // count >> 4
|
||||
add w10, w3, #1 // count + (count < 32)
|
||||
add w2, w2, #4 // rate = (count >> 4) | 4
|
||||
|
||||
sub w9, w9, w15 // cdf[0] -= bit
|
||||
sub w11, w9, w15, lsl #15 // {cdf[0], cdf[0] - 32769}
|
||||
asr w11, w11, w2 // {cdf[0], cdf[0] - 32769} >> rate
|
||||
sub w9, w9, w11 // cdf[0]
|
||||
|
||||
strh w9, [x1]
|
||||
strh w10, [x1, #2]
|
||||
|
||||
1:
|
||||
lsl w4, w4, w5 // rng << d
|
||||
subs w6, w6, w5 // cnt -= d
|
||||
lsl x7, x7, x5 // (dif - (v << 48)) << d
|
||||
str w4, [x0, #RNG]
|
||||
b.lo L(refill)
|
||||
|
||||
str w6, [x0, #CNT]
|
||||
str x7, [x0, #DIF]
|
||||
mov w0, w15
|
||||
ret
|
||||
endfunc
|
||||
546
media/libdav1d/src/src/arm/64/refmvs.S
Normal file
546
media/libdav1d/src/src/arm/64/refmvs.S
Normal file
|
|
@ -0,0 +1,546 @@
|
|||
/*
|
||||
* Copyright © 2021, VideoLAN and dav1d authors
|
||||
* Copyright © 2021, Martin Storsjo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "src/arm/asm-offsets.h"
|
||||
#include "src/arm/asm.S"
|
||||
#include "util.S"
|
||||
|
||||
#define INVALID_MV 0x80008000
|
||||
|
||||
// void dav1d_splat_mv_neon(refmvs_block **rr, const refmvs_block *rmv,
|
||||
// int bx4, int bw4, int bh4)
|
||||
|
||||
function splat_mv_neon, export=1
|
||||
ld1 {v3.16b}, [x1]
|
||||
clz w3, w3
|
||||
movrel x5, splat_tbl
|
||||
sub w3, w3, #26
|
||||
ext v2.16b, v3.16b, v3.16b, #12
|
||||
ldrsw x3, [x5, w3, uxtw #2]
|
||||
add w2, w2, w2, lsl #1
|
||||
ext v0.16b, v2.16b, v3.16b, #4
|
||||
add x3, x5, x3
|
||||
ext v1.16b, v2.16b, v3.16b, #8
|
||||
lsl w2, w2, #2
|
||||
ext v2.16b, v2.16b, v3.16b, #12
|
||||
1:
|
||||
ldr x1, [x0], #8
|
||||
subs w4, w4, #1
|
||||
add x1, x1, x2
|
||||
br x3
|
||||
|
||||
10:
|
||||
AARCH64_VALID_JUMP_TARGET
|
||||
st1 {v0.8b}, [x1]
|
||||
str s2, [x1, #8]
|
||||
b.gt 1b
|
||||
ret
|
||||
20:
|
||||
AARCH64_VALID_JUMP_TARGET
|
||||
st1 {v0.16b}, [x1]
|
||||
str d1, [x1, #16]
|
||||
b.gt 1b
|
||||
ret
|
||||
320:
|
||||
AARCH64_VALID_JUMP_TARGET
|
||||
st1 {v0.16b, v1.16b, v2.16b}, [x1], #48
|
||||
st1 {v0.16b, v1.16b, v2.16b}, [x1], #48
|
||||
st1 {v0.16b, v1.16b, v2.16b}, [x1], #48
|
||||
st1 {v0.16b, v1.16b, v2.16b}, [x1], #48
|
||||
160:
|
||||
AARCH64_VALID_JUMP_TARGET
|
||||
st1 {v0.16b, v1.16b, v2.16b}, [x1], #48
|
||||
st1 {v0.16b, v1.16b, v2.16b}, [x1], #48
|
||||
80:
|
||||
AARCH64_VALID_JUMP_TARGET
|
||||
st1 {v0.16b, v1.16b, v2.16b}, [x1], #48
|
||||
40:
|
||||
AARCH64_VALID_JUMP_TARGET
|
||||
st1 {v0.16b, v1.16b, v2.16b}, [x1]
|
||||
b.gt 1b
|
||||
ret
|
||||
endfunc
|
||||
|
||||
jumptable splat_tbl
|
||||
.word 320b - splat_tbl
|
||||
.word 160b - splat_tbl
|
||||
.word 80b - splat_tbl
|
||||
.word 40b - splat_tbl
|
||||
.word 20b - splat_tbl
|
||||
.word 10b - splat_tbl
|
||||
endjumptable
|
||||
|
||||
const mv_tbls, align=4
|
||||
.byte 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
|
||||
.byte 0, 1, 2, 3, 8, 0, 1, 2, 3, 8, 0, 1, 2, 3, 8, 0
|
||||
.byte 4, 5, 6, 7, 9, 4, 5, 6, 7, 9, 4, 5, 6, 7, 9, 4
|
||||
.byte 4, 5, 6, 7, 9, 4, 5, 6, 7, 9, 4, 5, 6, 7, 9, 4
|
||||
endconst
|
||||
|
||||
const mask_mult, align=4
|
||||
.byte 1, 2, 1, 2, 0, 0, 0, 0
|
||||
endconst
|
||||
|
||||
// void dav1d_save_tmvs_neon(refmvs_temporal_block *rp, ptrdiff_t stride,
|
||||
// refmvs_block **rr, const uint8_t *ref_sign,
|
||||
// int col_end8, int row_end8,
|
||||
// int col_start8, int row_start8)
|
||||
function save_tmvs_neon, export=1
|
||||
AARCH64_SIGN_LINK_REGISTER
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
|
||||
movi v30.8b, #0
|
||||
ld1 {v31.8b}, [x3]
|
||||
movrel x8, save_tmvs_tbl
|
||||
movrel x16, mask_mult
|
||||
movrel x13, mv_tbls
|
||||
ld1 {v29.8b}, [x16]
|
||||
ext v31.8b, v30.8b, v31.8b, #7 // [0, ref_sign]
|
||||
mov w15, #5
|
||||
mov w14, #12*2
|
||||
sxtw x4, w4
|
||||
sxtw x6, w6
|
||||
mul w1, w1, w15 // stride *= 5
|
||||
sub w5, w5, w7 // h = row_end8 - row_start8
|
||||
lsl w7, w7, #1 // row_start8 <<= 1
|
||||
1:
|
||||
mov w15, #5
|
||||
and w9, w7, #30 // (y & 15) * 2
|
||||
ldr x9, [x2, w9, uxtw #3] // b = rr[(y & 15) * 2]
|
||||
add x9, x9, #12 // &b[... + 1]
|
||||
madd x10, x4, x14, x9 // end_cand_b = &b[col_end8*2 + 1]
|
||||
madd x9, x6, x14, x9 // cand_b = &b[x*2 + 1]
|
||||
|
||||
madd x3, x6, x15, x0 // &rp[x]
|
||||
|
||||
2:
|
||||
ldrb w11, [x9, #10] // cand_b->bs
|
||||
ld1 {v0.16b}, [x9] // cand_b->mv
|
||||
add x11, x8, w11, uxtw #3
|
||||
ldr h1, [x9, #8] // cand_b->ref
|
||||
ldr w12, [x11] // bw8
|
||||
mov x15, x8
|
||||
add x9, x9, w12, uxtw #1 // cand_b += bw8*2
|
||||
cmp x9, x10
|
||||
mov v2.8b, v0.8b
|
||||
b.ge 3f
|
||||
|
||||
ldrb w15, [x9, #10] // cand_b->bs
|
||||
add x16, x9, #8
|
||||
ld1 {v4.16b}, [x9] // cand_b->mv
|
||||
add x15, x8, w15, uxtw #3
|
||||
ld1 {v1.h}[1], [x16] // cand_b->ref
|
||||
ldr w12, [x15] // bw8
|
||||
add x9, x9, w12, uxtw #1 // cand_b += bw8*2
|
||||
trn1 v2.2d, v0.2d, v4.2d
|
||||
|
||||
3:
|
||||
abs v2.8h, v2.8h // abs(mv[].xy)
|
||||
tbl v1.8b, {v31.16b}, v1.8b // ref_sign[ref]
|
||||
ushr v2.8h, v2.8h, #12 // abs(mv[].xy) >> 12
|
||||
umull v1.8h, v1.8b, v29.8b // ref_sign[ref] * {1, 2}
|
||||
cmeq v2.4s, v2.4s, #0 // abs(mv[].xy) <= 4096
|
||||
xtn v2.4h, v2.4s // abs() condition to 16 bit
|
||||
and v1.8b, v1.8b, v2.8b // h[0-3] contains conditions for mv[0-1]
|
||||
addp v1.4h, v1.4h, v1.4h // Combine condition for [1] and [0]
|
||||
umov w16, v1.h[0] // Extract case for first block
|
||||
umov w17, v1.h[1]
|
||||
ldrsw x11, [x11, #4] // Fetch jump table entry
|
||||
ldrsw x15, [x15, #4]
|
||||
ldr q1, [x13, w16, uxtw #4] // Load permutation table base on case
|
||||
ldr q5, [x13, w17, uxtw #4]
|
||||
add x11, x8, x11 // Find jump table target
|
||||
add x15, x8, x15
|
||||
tbl v0.16b, {v0.16b}, v1.16b // Permute cand_b to output refmvs_temporal_block
|
||||
tbl v4.16b, {v4.16b}, v5.16b
|
||||
|
||||
// v1 follows on v0, with another 3 full repetitions of the pattern.
|
||||
ext v1.16b, v0.16b, v0.16b, #1
|
||||
ext v5.16b, v4.16b, v4.16b, #1
|
||||
// v2 ends with 3 complete repetitions of the pattern.
|
||||
ext v2.16b, v0.16b, v1.16b, #4
|
||||
ext v6.16b, v4.16b, v5.16b, #4
|
||||
|
||||
blr x11
|
||||
b.ge 4f // if (cand_b >= end)
|
||||
mov v0.16b, v4.16b
|
||||
mov v1.16b, v5.16b
|
||||
mov v2.16b, v6.16b
|
||||
cmp x9, x10
|
||||
blr x15
|
||||
b.lt 2b // if (cand_b < end)
|
||||
|
||||
4:
|
||||
subs w5, w5, #1 // h--
|
||||
add w7, w7, #2 // y += 2
|
||||
add x0, x0, x1 // rp += stride
|
||||
b.gt 1b
|
||||
|
||||
ldp x29, x30, [sp], #16
|
||||
AARCH64_VALIDATE_LINK_REGISTER
|
||||
ret
|
||||
|
||||
10:
|
||||
AARCH64_VALID_CALL_TARGET
|
||||
add x16, x3, #4
|
||||
st1 {v0.s}[0], [x3]
|
||||
st1 {v0.b}[4], [x16]
|
||||
add x3, x3, #5
|
||||
ret
|
||||
20:
|
||||
AARCH64_VALID_CALL_TARGET
|
||||
add x16, x3, #8
|
||||
st1 {v0.d}[0], [x3]
|
||||
st1 {v0.h}[4], [x16]
|
||||
add x3, x3, #2*5
|
||||
ret
|
||||
40:
|
||||
AARCH64_VALID_CALL_TARGET
|
||||
st1 {v0.16b}, [x3]
|
||||
str s1, [x3, #16]
|
||||
add x3, x3, #4*5
|
||||
ret
|
||||
80:
|
||||
AARCH64_VALID_CALL_TARGET
|
||||
// This writes 6 full entries plus 2 extra bytes
|
||||
st1 {v0.16b, v1.16b}, [x3]
|
||||
// Write the last few, overlapping with the first write.
|
||||
stur q2, [x3, #(8*5-16)]
|
||||
add x3, x3, #8*5
|
||||
ret
|
||||
160:
|
||||
AARCH64_VALID_CALL_TARGET
|
||||
add x16, x3, #6*5
|
||||
add x17, x3, #12*5
|
||||
// This writes 6 full entries plus 2 extra bytes
|
||||
st1 {v0.16b, v1.16b}, [x3]
|
||||
// Write another 6 full entries, slightly overlapping with the first set
|
||||
st1 {v0.16b, v1.16b}, [x16]
|
||||
// Write 8 bytes (one full entry) after the first 12
|
||||
st1 {v0.8b}, [x17]
|
||||
// Write the last 3 entries
|
||||
str q2, [x3, #(16*5-16)]
|
||||
add x3, x3, #16*5
|
||||
ret
|
||||
endfunc
|
||||
|
||||
jumptable save_tmvs_tbl
|
||||
.word 16 * 12
|
||||
.word 160b - save_tmvs_tbl
|
||||
.word 16 * 12
|
||||
.word 160b - save_tmvs_tbl
|
||||
.word 8 * 12
|
||||
.word 80b - save_tmvs_tbl
|
||||
.word 8 * 12
|
||||
.word 80b - save_tmvs_tbl
|
||||
.word 8 * 12
|
||||
.word 80b - save_tmvs_tbl
|
||||
.word 8 * 12
|
||||
.word 80b - save_tmvs_tbl
|
||||
.word 4 * 12
|
||||
.word 40b - save_tmvs_tbl
|
||||
.word 4 * 12
|
||||
.word 40b - save_tmvs_tbl
|
||||
.word 4 * 12
|
||||
.word 40b - save_tmvs_tbl
|
||||
.word 4 * 12
|
||||
.word 40b - save_tmvs_tbl
|
||||
.word 2 * 12
|
||||
.word 20b - save_tmvs_tbl
|
||||
.word 2 * 12
|
||||
.word 20b - save_tmvs_tbl
|
||||
.word 2 * 12
|
||||
.word 20b - save_tmvs_tbl
|
||||
.word 2 * 12
|
||||
.word 20b - save_tmvs_tbl
|
||||
.word 2 * 12
|
||||
.word 20b - save_tmvs_tbl
|
||||
.word 1 * 12
|
||||
.word 10b - save_tmvs_tbl
|
||||
.word 1 * 12
|
||||
.word 10b - save_tmvs_tbl
|
||||
.word 1 * 12
|
||||
.word 10b - save_tmvs_tbl
|
||||
.word 1 * 12
|
||||
.word 10b - save_tmvs_tbl
|
||||
.word 1 * 12
|
||||
.word 10b - save_tmvs_tbl
|
||||
.word 1 * 12
|
||||
.word 10b - save_tmvs_tbl
|
||||
.word 1 * 12
|
||||
.word 10b - save_tmvs_tbl
|
||||
endjumptable
|
||||
|
||||
// void dav1d_load_tmvs_neon(const refmvs_frame *const rf, int tile_row_idx,
|
||||
// const int col_start8, const int col_end8,
|
||||
// const int row_start8, int row_end8)
|
||||
function load_tmvs_neon, export=1
|
||||
rf .req x0
|
||||
tile_row_idx .req w1
|
||||
col_start8 .req w2
|
||||
col_end8 .req w3
|
||||
row_start8 .req w4
|
||||
row_end8 .req w5
|
||||
col_start8i .req w6
|
||||
col_end8i .req w7
|
||||
rp_proj .req x8
|
||||
stride5 .req x9
|
||||
wstride5 .req w9
|
||||
stp x28, x27, [sp, #-96]!
|
||||
stp x26, x25, [sp, #16]
|
||||
stp x24, x23, [sp, #32]
|
||||
stp x22, x21, [sp, #48]
|
||||
stp x20, x19, [sp, #64]
|
||||
stp x29, x30, [sp, #80]
|
||||
|
||||
ldr w15, [rf, #RMVSF_N_TILE_THREADS]
|
||||
ldp w16, w17, [rf, #RMVSF_IW8] // include rf->ih8 too
|
||||
sub col_start8i, col_start8, #8 // col_start8 - 8
|
||||
add col_end8i, col_end8, #8 // col_end8 + 8
|
||||
ldr wstride5, [rf, #RMVSF_RP_STRIDE]
|
||||
ldr rp_proj, [rf, #RMVSF_RP_PROJ]
|
||||
|
||||
cmp w15, #1
|
||||
csel tile_row_idx, wzr, tile_row_idx, eq // if (rf->n_tile_threads == 1) tile_row_idx = 0
|
||||
|
||||
bic col_start8i, col_start8i, col_start8i, asr #31 // imax(col_start8 - 8, 0)
|
||||
cmp col_end8i, w16
|
||||
csel col_end8i, col_end8i, w16, lt // imin(col_end8 + 8, rf->iw8)
|
||||
|
||||
lsl tile_row_idx, tile_row_idx, #4 // 16 * tile_row_idx
|
||||
|
||||
cmp row_end8, w17
|
||||
csel row_end8, row_end8, w17, lt // imin(row_end8, rf->ih8)
|
||||
|
||||
add wstride5, wstride5, wstride5, lsl #2 // stride * sizeof(refmvs_temporal_block)
|
||||
and w15, row_start8, #15 // row_start8 & 15
|
||||
add w10, col_start8, col_start8, lsl #2 // col_start8 * sizeof(refmvs_temporal_block)
|
||||
smaddl rp_proj, tile_row_idx, wstride5, rp_proj // &rf->rp_proj[16 * stride * tile_row_idx]
|
||||
smaddl x10, w15, wstride5, x10 // ((row_start8 & 15) * stride + col_start8) * sizeof(refmvs_temporal_block)
|
||||
mov w15, #INVALID_MV
|
||||
sub w11, col_end8, col_start8 // xfill loop count
|
||||
add x10, x10, rp_proj // &rf->rp_proj[16 * stride * tile_row_idx + (row_start8 & 15) * stride + col_start8]
|
||||
add x15, x15, x15, lsl #40 // first 64b of 4 [INVALID_MV, 0]... patterns
|
||||
mov w17, #(INVALID_MV >> 8) // last 32b of 4 patterns
|
||||
sub w12, row_end8, row_start8 // yfill loop count
|
||||
ror x16, x15, #48 // second 64b of 4 patterns
|
||||
ldr w19, [rf, #RMVSF_N_MFMVS]
|
||||
|
||||
5: // yfill loop
|
||||
and w13, w11, #-4 // xfill 4x count by patterns
|
||||
mov x14, x10 // fill_ptr = row_ptr
|
||||
add x10, x10, stride5 // row_ptr += stride
|
||||
sub w12, w12, #1 // y--
|
||||
|
||||
cbz w13, 3f
|
||||
|
||||
4: // xfill loop 4x
|
||||
sub w13, w13, #4 // xfill 4x count -= 4
|
||||
stp x15, x16, [x14]
|
||||
str w17, [x14, #16]
|
||||
add x14, x14, #20 // fill_ptr += 4 * sizeof(refmvs_temporal_block)
|
||||
cbnz w13, 4b
|
||||
|
||||
3: // up to 3 residuals
|
||||
tbz w11, #1, 1f
|
||||
str x15, [x14]
|
||||
strh w16, [x14, #8]
|
||||
add x14, x14, #10 // fill_ptr += 2 * sizeof(refmvs_temporal_block)
|
||||
|
||||
1: // up to 1 residual
|
||||
tbz w11, #0, 2f
|
||||
str w15, [x14]
|
||||
2:
|
||||
cbnz w12, 5b // yfill loop
|
||||
|
||||
cbz w19, 11f // if (!rf->n_mfmvs) skip nloop
|
||||
|
||||
add x29, rf, #RMVSF_MFMV_REF2CUR
|
||||
mov w10, #0 // n = 0
|
||||
movi v3.2s, #255 // 0x3FFF >> 6, for MV clamp
|
||||
movrel x1, div_mult_tbl
|
||||
|
||||
10: // nloop
|
||||
ldrsb w16, [x29, x10] // ref2cur = rf->mfmv_ref2cur[n]
|
||||
cmp w16, #-32
|
||||
b.eq 9f // if (ref2cur == INVALID_REF2CUR) continue
|
||||
|
||||
add x17, x10, #(RMVSF_MFMV_REF - RMVSF_MFMV_REF2CUR) // n - (&rf->mfmv_ref - &rf->mfmv_ref2cur)
|
||||
mov x20, #4
|
||||
ldrb w17, [x29, x17] // ref = rf->mfmv_ref[n]
|
||||
ldr x13, [x29, #(RMVSF_RP_REF - RMVSF_MFMV_REF2CUR)]
|
||||
sub x21, x10, x10, lsl #3 // -(n * 7)
|
||||
smaddl x20, row_start8, wstride5, x20 // row_start8 * stride * sizeof(refmvs_temporal_block) + 4
|
||||
mov w12, row_start8 // y = row_start8
|
||||
add x28, x29, #(RMVSF_MFMV_REF2REF - RMVSF_MFMV_REF2CUR - 1) // &rf->mfmv_ref2ref - 1
|
||||
ldr x13, [x13, x17, lsl #3] // rf->rp_ref[ref]
|
||||
sub x28, x28, x21 // rf->mfmv_ref2ref[n] - 1
|
||||
sub w17, w17, #4 // ref_sign = ref - 4
|
||||
add x13, x13, x20 // r = &rf->rp_ref[ref][row_start8 * stride].ref
|
||||
dup v0.2s, w17 // ref_sign
|
||||
|
||||
5: // yloop
|
||||
and w14, w12, #-8 // y_sb_align = y & ~7
|
||||
mov w11, col_start8i // x = col_start8i
|
||||
add w15, w14, #8 // y_sb_align + 8
|
||||
cmp w14, row_start8
|
||||
csel w14, w14, row_start8, gt // imax(y_sb_align, row_start8)
|
||||
cmp w15, row_end8
|
||||
csel w15, w15, row_end8, lt // imin(y_sb_align + 8, row_end8)
|
||||
|
||||
4: // xloop
|
||||
add x23, x13, x11, lsl #2 // partial &r[x] address
|
||||
ldrb w22, [x23, x11] // b_ref = rb->ref
|
||||
cbz w22, 6f // if (!b_ref) continue
|
||||
|
||||
ldrb w24, [x28, x22] // ref2ref = rf->mfmv_ref2ref[n][b_ref - 1]
|
||||
cbz w24, 6f // if (!ref2ref) continue
|
||||
|
||||
ldrh w20, [x1, x24, lsl #1] // div_mult[ref2ref]
|
||||
add x23, x23, x11 // &r[x]
|
||||
mul w20, w20, w16 // frac = ref2cur * div_mult[ref2ref]
|
||||
|
||||
ldur s1, [x23, #-4] // mv{y, x} = rb->mv
|
||||
fmov s2, w20 // frac
|
||||
sxtl v1.4s, v1.4h
|
||||
mul v1.2s, v1.2s, v2.s[0] // offset{y, x} = frac * mv{y, x}
|
||||
|
||||
ssra v1.2s, v1.2s, #31 // offset{y, x} + (offset{y, x} >> 31)
|
||||
ldur w25, [x23, #-4] // b_mv = rb->mv
|
||||
srshr v1.2s, v1.2s, #14 // (offset{y, x} + (offset{y, x} >> 31) + 8192) >> 14
|
||||
|
||||
abs v2.2s, v1.2s // abs(offset{y, x})
|
||||
eor v1.8b, v1.8b, v0.8b // offset{y, x} ^ ref_sign
|
||||
|
||||
sshr v2.2s, v2.2s, #6 // abs(offset{y, x}) >> 6
|
||||
cmlt v1.2s, v1.2s, #0 // sign(offset{y, x} ^ ref_sign): -1 or 0
|
||||
umin v2.2s, v2.2s, v3.2s // iclip(abs(offset{y, x}) >> 6, 0, 0x3FFF >> 6)
|
||||
|
||||
neg v4.2s, v2.2s
|
||||
bsl v1.8b, v4.8b, v2.8b // apply_sign(iclip(abs(offset{y, x}) >> 6, 0, 0x3FFF >> 6))
|
||||
fmov x20, d1 // offset{y, x}
|
||||
|
||||
add w21, w12, w20 // pos_y = y + offset.y
|
||||
cmp w21, w14 // pos_y >= y_proj_start
|
||||
b.lt 1f
|
||||
cmp w21, w15 // pos_y < y_proj_end
|
||||
b.ge 1f
|
||||
add x26, x11, x20, asr #32 // pos_x = x + offset.x
|
||||
and w27, w21, #15 // pos_y & 15
|
||||
add x21, x26, x26, lsl #2 // pos_x * sizeof(refmvs_temporal_block)
|
||||
umaddl x27, w27, wstride5, rp_proj // &rp_proj[(pos_y & 15) * stride]
|
||||
add x27, x27, x21 // &rp_proj[(pos_y & 15) * stride + pos_x]
|
||||
|
||||
3: // copy loop
|
||||
and w20, w11, #-8 // x_sb_align = x & ~7
|
||||
sub w21, w20, #8 // x_sb_align - 8
|
||||
cmp w21, col_start8
|
||||
csel w21, w21, col_start8, gt // imax(x_sb_align - 8, col_start8)
|
||||
cmp w26, w21 // pos_x >= imax(x_sb_align - 8, col_start8)
|
||||
b.lt 2f
|
||||
add w20, w20, #16 // x_sb_align + 16
|
||||
cmp w20, col_end8
|
||||
csel w20, w20, col_end8, lt // imin(x_sb_align + 16, col_end8)
|
||||
cmp w26, w20 // pos_x < imin(x_sb_align + 16, col_end8)
|
||||
b.ge 2f
|
||||
str w25, [x27] // rp_proj[pos + pos_x].mv = rb->mv (b_mv)
|
||||
strb w24, [x27, #4] // rp_proj[pos + pos_x].ref = ref2ref
|
||||
|
||||
2: // search part of copy loop
|
||||
add w11, w11, #1 // x++
|
||||
cmp w11, col_end8i // if (++x >= col_end8i) break xloop
|
||||
b.ge 8f
|
||||
|
||||
ldrb w20, [x23, #5]! // rb++; rb->ref
|
||||
cmp w20, w22 // if (rb->ref != b_ref) break
|
||||
b.ne 7f
|
||||
|
||||
ldur w21, [x23, #-4] // rb->mv.n
|
||||
cmp w21, w25 // if (rb->mv.n != b_mv.n) break
|
||||
b.ne 7f
|
||||
|
||||
add w26, w26, #1 // pos_x++
|
||||
add x27, x27, #5 // advance &rp_proj[(pos_y & 15) * stride + pos_x]
|
||||
b 3b // copy loop
|
||||
|
||||
1: // search loop
|
||||
add w11, w11, #1 // x++
|
||||
cmp w11, col_end8i // if (++x >= col_end8i) break xloop
|
||||
b.ge 8f
|
||||
|
||||
ldrb w20, [x23, #5]! // rb++; rb->ref
|
||||
cmp w20, w22 // if (rb->ref != b_ref) break
|
||||
b.ne 7f
|
||||
|
||||
ldur w21, [x23, #-4] // rb->mv.n
|
||||
cmp w21, w25 // if (rb->mv.n == b_mv.n) continue
|
||||
b.eq 1b // search loop
|
||||
7:
|
||||
cmp w11, col_end8i // x < col_end8i
|
||||
b.lt 4b // xloop
|
||||
|
||||
6: // continue case of xloop
|
||||
add w11, w11, #1 // x++
|
||||
cmp w11, col_end8i // x < col_end8i
|
||||
b.lt 4b // xloop
|
||||
8:
|
||||
add w12, w12, #1 // y++
|
||||
add x13, x13, stride5 // r += stride
|
||||
cmp w12, row_end8 // y < row_end8
|
||||
b.lt 5b // yloop
|
||||
9:
|
||||
add w10, w10, #1
|
||||
cmp w10, w19 // n < rf->n_mfmvs
|
||||
b.lt 10b // nloop
|
||||
11:
|
||||
ldp x29, x30, [sp, #80]
|
||||
ldp x20, x19, [sp, #64]
|
||||
ldp x22, x21, [sp, #48]
|
||||
ldp x24, x23, [sp, #32]
|
||||
ldp x26, x25, [sp, #16]
|
||||
ldp x28, x27, [sp], #96
|
||||
ret
|
||||
.unreq rf
|
||||
.unreq tile_row_idx
|
||||
.unreq col_start8
|
||||
.unreq col_end8
|
||||
.unreq row_start8
|
||||
.unreq row_end8
|
||||
.unreq col_start8i
|
||||
.unreq col_end8i
|
||||
.unreq rp_proj
|
||||
.unreq stride5
|
||||
.unreq wstride5
|
||||
endfunc
|
||||
|
||||
const div_mult_tbl
|
||||
.hword 0, 16384, 8192, 5461, 4096, 3276, 2730, 2340
|
||||
.hword 2048, 1820, 1638, 1489, 1365, 1260, 1170, 1092
|
||||
.hword 1024, 963, 910, 862, 819, 780, 744, 712
|
||||
.hword 682, 655, 630, 606, 585, 564, 546, 528
|
||||
endconst
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue