diff --git a/.cmake-format.py b/.cmake-format.py new file mode 100644 index 0000000..cbd6182 --- /dev/null +++ b/.cmake-format.py @@ -0,0 +1,28 @@ +# ----------------------------- +# Options affecting formatting. +# ----------------------------- +with section("format"): + # How wide to allow formatted cmake files + line_width = 130 + + # How many spaces to tab for indent + tab_size = 4 + + # If an argument group contains more than this many sub-groups (parg or kwarg + # groups) then force it to a vertical layout. + max_subgroups_hwrap = 3 + + # If a positional argument group contains more than this many arguments, then + # force it to a vertical layout. + max_pargs_hwrap = 10 + + # If a statement is wrapped to more than one line, than dangle the closing + # parenthesis on its own line. + dangle_parens = True + +# ------------------------------------------------ +# Options affecting comment reflow and formatting. +# ------------------------------------------------ +with section("markup"): + # enable comment markup parsing and reflow + enable_markup = False diff --git a/.gitattributes b/.gitattributes index efdba87..4fb4d21 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ * text=auto *.sh text eol=lf +*.y4m -text -diff diff --git a/.github/actions/cache/action.yml b/.github/actions/cache/action.yml new file mode 100644 index 0000000..889c050 --- /dev/null +++ b/.github/actions/cache/action.yml @@ -0,0 +1,65 @@ +name: 'Cache for all OSes' +description: 'Needs to be called before any call to ext/.cmd|sh or cmake' +inputs: + extra-key: + description: 'Extra cache key to use in the cache name. Useful when several caches are used in one workflow.' + default: '' + use-meson: + description: 'Whether meson is used' + default: false + use-rust: + description: 'Whether rust is used' + default: false +outputs: + ext-cache-hit: + value: ${{ steps.cache-ext.outputs.cache-hit }} +runs: + using: "composite" + steps: + - name: Find workflow path + env: + WORKFLOW_REF: ${{ github.workflow_ref }} + id: workflow-info + run: | + # Remove repository path. + END=(${WORKFLOW_REF/*.github/.github}) + # Remove branch reference starting with @. + MIDDLE=(${END/%@*/}) + echo "Current workflow path is: ${MIDDLE}" + echo "path=${MIDDLE}" >> "$GITHUB_OUTPUT" + shell: bash + - name: Generate meson cache key + if: ${{ inputs.use-meson == 'true' }} + run: | + echo "MESON_KEY=meson-`meson --version`" >> $GITHUB_ENV + shell: bash + - name: Generate empty meson cache key + if: ${{ inputs.use-meson != 'true' }} + run: | + echo "MESON_KEY=meson-none" >> $GITHUB_ENV + shell: bash + - name: Generate cargo cache key + if: ${{ inputs.use-rust == 'true' }} + id: cargo-key + run: | + echo "key=cargo-registry-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ inputs.extra-key }}-${{ hashFiles('.github/action/**', steps.workflow-info.outputs.path, 'CMakeLists.txt', 'cmake/Modules/Findrav1e.cmake', 'cmake/Modules/LocalRav1e.cmake', 'ext/rav1e.cmd') }}" >> "$GITHUB_OUTPUT" + shell: bash + - name: Cache all of cargo + if: ${{ inputs.use-rust == 'true' }} + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + continue-on-error: true + with: + path: ~/.cargo + key: ${{ steps.cargo-key.outputs.key }}-${{ github.run_id }} + restore-keys: ${{ steps.cargo-key.outputs.key }} + - name: Cache external dependencies in ext + id: cache-ext + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ext + key: ext-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ inputs.extra-key }}-${{ env.MESON_KEY }}-${{ hashFiles('.github/action/**', steps.workflow-info.outputs.path, 'ext/*.cmd', 'ext/*.sh') }} + - name: Cache external dependencies in build/_deps + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: build/_deps + key: deps-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ inputs.extra-key }}-${{ env.MESON_KEY }}-${{ hashFiles('.github/action/**', steps.workflow-info.outputs.path, 'CMakeLists.txt', 'cmake/Modules/*') }} diff --git a/.github/actions/setup-common/action.yml b/.github/actions/setup-common/action.yml new file mode 100644 index 0000000..e1454dc --- /dev/null +++ b/.github/actions/setup-common/action.yml @@ -0,0 +1,47 @@ +name: 'Common setup for all OSes' +description: 'Installs common dependencies' +inputs: + codec-aom: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + codec-dav1d: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + codec-rav1e: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + recent-cmake: + description: 'Can take the values: true, false. Only useful on Linux' + default: 'false' +runs: + using: "composite" + steps: + - name: Set up Python + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + with: + python-version: '3.x' + - name: Set up CMake < 3.18 + if: ${{ runner.os == 'Linux' && inputs.recent-cmake == 'false' }} + uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2.0.2 + with: + cmake-version: '3.13.x' + - name: Set up CMake >= 3.18 + if: ${{ runner.os == 'Linux' && inputs.recent-cmake == 'true' }} + uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2.0.2 + with: + cmake-version: '3.18.x' + - name: Print CMake version + run: cmake --version + shell: bash + - name: Set up ninja + uses: seanmiddleditch/gha-setup-ninja@8b297075da4cd2a5f1fd21fe011b499edf06e9d2 # v4 + - name: Set up nasm + if: ${{ inputs.codec-aom == 'LOCAL' || inputs.codec-dav1d == 'LOCAL' }} + uses: ilammy/setup-nasm@13cbeb366c45c4379d3478cdcbadd8295feb5028 # v1.5.1 + - name: Set up rust + if: ${{ inputs.codec-rav1e == 'LOCAL' }} + uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # v1.0.7 + with: + profile: minimal + toolchain: stable + override: true diff --git a/.github/actions/setup-linux/action.yml b/.github/actions/setup-linux/action.yml new file mode 100644 index 0000000..ac9c0d3 --- /dev/null +++ b/.github/actions/setup-linux/action.yml @@ -0,0 +1,94 @@ +name: 'Setup on Linux' +description: 'Installs dependencies and sets env variables specific to Linux' +inputs: + codec-aom: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + codec-dav1d: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + edfault: 'OFF' + codec-rav1e: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + extra-cache-key: + description: 'Extra cache key to use in the cache name. Useful when several caches are used in one workflow.' + default: '' + gcc-version: + description: 'Can be empty, in which case CC and CXX are not overriden' + default: '' + gtest: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + libxml2: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + libyuv: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + recent-cmake: + description: 'Can take the values: true, false' + default: 'false' +outputs: + ext-cache-hit: + value: ${{ steps.cache.outputs.ext-cache-hit }} +runs: + using: "composite" + steps: + - name: Install non-library dependencies + run: | + sudo apt update -y + sudo apt install -y imagemagick libjpeg-turbo8-dev libpng-dev + shell: bash + - name: Install libaom library + if: ${{ inputs.codec-aom == 'SYSTEM' }} + run: + sudo apt install -y libaom-dev + shell: bash + - name: Install libdav1d library + if: ${{ inputs.codec-dav1d == 'SYSTEM' }} + run: + sudo apt install -y libdav1d-dev + shell: bash + - name: Install rav1e library + if: ${{ inputs.codec-rav1e == 'SYSTEM' }} + run: + sudo apt install -y librav1e-dev + shell: bash + - name: Install libxml2 library + if: ${{ inputs.libxml2 == 'SYSTEM' }} + run: + sudo apt install -y libxml2 + shell: bash + - name: Install libyuv library + if: ${{ inputs.libyuv == 'SYSTEM' }} + run: + sudo apt install -y libyuv-dev + shell: bash + - name: Set up meson + if: ${{ inputs.codec-dav1d == 'LOCAL' }} + run: + sudo apt install -y meson + shell: bash + - name: Set up gtest + if: ${{ inputs.gtest == 'SYSTEM' }} + run: + sudo apt install -y libgtest-dev + shell: bash + + - uses: ./.github/actions/setup-common + with: + codec-aom: ${{ inputs.codec-aom }} + codec-dav1d: ${{ inputs.codec-dav1d }} + codec-rav1e: ${{ inputs.codec-rav1e }} + recent-cmake: ${{ inputs.recent-cmake }} + - uses: ./.github/actions/cache + id: cache + with: + extra-key: ${{ inputs.extra-cache-key }} + use-meson: ${{ inputs.codec-dav1d == 'LOCAL' }} + use-rust: ${{ inputs.codec-rav1e == 'LOCAL' }} + + - name: Set GCC & G++ compiler + if: ${{ inputs.gcc-version != '' }} + run: echo "CC=gcc-${{ inputs.gcc-version }}" >> $GITHUB_ENV && echo "CXX=g++-${{ inputs.gcc-version }}" >> $GITHUB_ENV + shell: bash diff --git a/.github/actions/setup-macos/action.yml b/.github/actions/setup-macos/action.yml new file mode 100644 index 0000000..ad215b3 --- /dev/null +++ b/.github/actions/setup-macos/action.yml @@ -0,0 +1,67 @@ +name: 'Setup on macOS' +description: 'Installs dependencies specific to macOS' +inputs: + codec-aom: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + codec-dav1d: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + codec-rav1e: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + gtest: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + extra-cache-key: + description: 'Extra cache key to use in the cache name. Useful when several caches are used in one workflow.' + default: '' +outputs: + ext-cache-hit: + value: ${{ steps.cache.outputs.ext-cache-hit }} +runs: + using: "composite" + steps: + # github actions overwrites brew's python. Force it to reassert itself, by running in a separate step. + # Borrowed from https://github.com/mesonbuild/meson/blob/aab2533ab4f7f4c16991620b400d71782f89be1c/.github/workflows/macos.yml#L87-L92 + # until https://github.com/actions/setup-python/issues/577 is fixed. + - name: unbreak python in github actions + run: | + find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/2to3*' \ + -o -lname '*/Library/Frameworks/Python.framework/idle3*' \ + -o -lname '*/Library/Frameworks/Python.framework/pydoc3*' \ + -o -lname '*/Library/Frameworks/Python.framework/python3*' -delete + sudo rm -rf /Library/Frameworks/Python.framework/ + brew install --force python3 && brew unlink python3 && brew unlink python3 && brew link --overwrite python3 + shell: bash + - name: Install non-library dependencies + run: brew install imagemagick + shell: bash + - name: Install AOM library + if: ${{ inputs.codec-aom == 'SYSTEM' }} + run: brew install aom + shell: bash + - name: Install dav1d library + if: ${{ inputs.codec-dav1d == 'SYSTEM' }} + run: brew install dav1d + shell: bash + - name: Set up meson + if: ${{ inputs.codec-dav1d == 'LOCAL' }} + run: brew install meson + shell: bash + - name: Set up gtest + if: ${{ inputs.gtest == 'SYSTEM' }} + run: brew install googletest + shell: bash + + - uses: ./.github/actions/setup-common + with: + codec-aom: ${{ inputs.codec-aom }} + codec-dav1d: ${{ inputs.codec-dav1d }} + codec-rav1e: ${{ inputs.codec-rav1e }} + - uses: ./.github/actions/cache + id: cache + with: + extra-key: ${{ inputs.extra-cache-key }} + use-meson: ${{ inputs.codec-dav1d == 'LOCAL' }} + use-rust: ${{ inputs.codec-rav1e == 'LOCAL' }} diff --git a/.github/actions/setup-windows/action.yml b/.github/actions/setup-windows/action.yml new file mode 100644 index 0000000..07a3a48 --- /dev/null +++ b/.github/actions/setup-windows/action.yml @@ -0,0 +1,39 @@ +name: 'Setup on Windows' +description: 'Installs dependencies specific to Windows' +inputs: + codec-aom: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + codec-dav1d: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + codec-rav1e: + description: 'Can take the values: OFF, LOCAL, SYSTEM' + default: 'OFF' + extra-cache-key: + description: 'Extra cache key to use in the cache name. Useful when several caches are used in one workflow.' + default: '' +outputs: + ext-cache-hit: + value: ${{ steps.cache.outputs.ext-cache-hit }} +runs: + using: "composite" + steps: + - name: Setup Developer Command Prompt for Microsoft Visual C++ + uses: ilammy/msvc-dev-cmd@v1 + - name: Set up meson + if: ${{ inputs.codec-dav1d == 'LOCAL' }} + run: pip install meson + shell: bash + + - uses: ./.github/actions/setup-common + with: + codec-aom: ${{ inputs.codec-aom }} + codec-dav1d: ${{ inputs.codec-dav1d }} + codec-rav1e: ${{ inputs.codec-rav1e }} + - uses: ./.github/actions/cache + id: cache + with: + extra-key: ${{ inputs.extra-cache-key }} + use-meson: ${{ inputs.codec-dav1d == 'LOCAL' }} + use-rust: ${{ inputs.codec-rav1e == 'LOCAL' }} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..322a2b6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + groups: + github-actions: + patterns: + - "*" diff --git a/.github/workflows/build.ps1 b/.github/workflows/build.ps1 deleted file mode 100644 index 21a2fb1..0000000 --- a/.github/workflows/build.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -param ( - [Parameter(Mandatory)] $architecture, - [Parameter(Mandatory)] $vs -) - -$ErrorActionPreference = "Stop" - -if ($architecture -eq "x86") { - $platform = "Win32" -} else { - $platform = "x64" -} - -if ($vs -eq "vs16") { - $generator = "Visual Studio 16 2019" -} else { -} - -Set-Location "ext" -git clone -b "v2.0.2" --depth 1 "https://aomedia.googlesource.com/aom" -Set-Location "aom" -New-Item "build.libavif" -ItemType "directory" -Set-Location "build.libavif" -$on = if ($architecture -eq "x64") {"1"} else {"0"} -cmake "-G" "$generator" "-A" "$platform" "-DENABLE_DOCS=0" "-DENABLE_EXAMPLES=0" "-DENABLE_TESTDATA=0" "-DENABLE_TESTS=0" "-DENABLE_TOOLS=0" "-DENABLE_NASM=1" "-DENABLE_SSE2=$on" "-DENABLE_SSE3=$on" "-DENABLE_SSSE3=$on" "-DENABLE_SSE4_1=$on" "-DENABLE_SSE4_2=$on" "-DENABLE_AVX=$on" "-DENABLE_AVX2=$on" ".." -msbuild "/t:Build" "/p:Configuration=Release" "/p:Platform=$platform" "AOM.sln" -xcopy "Release\*.lib" "." -xcopy "Release\aom.lib" ".\aom_a.lib*" -xcopy ".\aom_a.lib" "..\..\..\winlibs\lib\" -Set-Location "..\..\.." - -cmake "$generator" -A "$platform" -DAVIF_CODEC_AOM=1 -DAVIF_LOCAL_AOM=1 -DAVIF_ENABLE_WERROR=0 -DBUILD_SHARED_LIBS=0 . -msbuild "/t:Build" "/p:Configuration=RelWithDebInfo" "/p:Platform=$platform" "libavif.sln" -xcopy "include\avif\avif.h" "winlibs\include\avif\*" -xcopy "RelWithDebInfo\avif*.??b" "winlibs\lib\*" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index f072789..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: build -on: [push, pull_request] -jobs: - build: - strategy: - matrix: - architecture: [x64, x86] - runs-on: windows-2019 - steps: - - uses: ilammy/setup-nasm@v1 - - uses: actions/checkout@v2 - - uses: microsoft/setup-msbuild@v1.0.2 - - run: powershell ./.github/workflows/build.ps1 ${{matrix.architecture}} vs16 - - uses: actions/upload-artifact@v2 - with: - name: libavif-${{github.sha}}-vs16-${{matrix.architecture}} - path: ./winlibs/ diff --git a/.github/workflows/ci-android-emulator-tests.yml b/.github/workflows/ci-android-emulator-tests.yml new file mode 100644 index 0000000..9cc5d1a --- /dev/null +++ b/.github/workflows/ci-android-emulator-tests.yml @@ -0,0 +1,62 @@ +name: CI Android Emulator Tests +on: + push: + branches: + - main + paths: + - '.github/workflows/ci-android-emulator-tests.yml' + - 'android_jni/**' + pull_request: + paths: + - '.github/workflows/ci-android-emulator-tests.yml' + - 'android_jni/**' + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-and-run-android-jni-tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + + steps: + - name: Checkout the repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + # This is needed for faster emulators. See: + # https://github.com/ReactiveCircus/android-emulator-runner?tab=readme-ov-file#running-hardware-accelerated-emulators-on-linux-runners + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + - name: Download and Setup the Android NDK + uses: nttld/setup-ndk@afb4c9964b521afb97c864b7d40b11e6911bd410 # v1.5.0 + id: setup-ndk + with: + # r25c is the same as 25.2.9519653. + ndk-version: r25c + add-to-path: false + - uses: ./.github/actions/setup-linux + with: + codec-dav1d: 'LOCAL' + libyuv: 'LOCAL' + - name: Setup JDK + uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + with: + java-version: '17' + distribution: 'temurin' + - name: Run Instrumented Tests on the Emulator + uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 # v2.31.0 + with: + working-directory: android_jni + api-level: 31 + force-avd-creation: false + ndk: 25.2.9519653 + arch: x86_64 + script: ./gradlew cAT diff --git a/.github/workflows/ci-android-jni.yml b/.github/workflows/ci-android-jni.yml new file mode 100644 index 0000000..097f153 --- /dev/null +++ b/.github/workflows/ci-android-jni.yml @@ -0,0 +1,48 @@ +name: CI Android JNI +on: [push, pull_request] + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-android-jni: + runs-on: ubuntu-latest + strategy: + fail-fast: false + + steps: + - name: Checkout the repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Download and Setup the Android NDK + uses: nttld/setup-ndk@afb4c9964b521afb97c864b7d40b11e6911bd410 # v1.5.0 + id: setup-ndk + with: + # r25c is the same as 25.2.9519653. + ndk-version: r25c + add-to-path: false + - uses: ./.github/actions/setup-linux + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + recent-cmake: 'true' + - name: Setup JDK + uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + with: + distribution: "zulu" + java-version: 17 + - name: Download and Setup the Android SDK + uses: android-actions/setup-android@00854ea68c109d98c75d956347303bf7c45b0277 # v3.2.1 + - name: Install CMake in the Android SDK + # This is the same version of cmake that is found in build.gradle. This + # will be used to build libavif and the JNI bindings. + run: sdkmanager "cmake;3.22.1" + - name: Build the libavif JNI Wrapper + working-directory: android_jni + run: ./gradlew --no-daemon assembleRelease + env: + ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} diff --git a/.github/workflows/ci-disable-gtest.yml b/.github/workflows/ci-disable-gtest.yml new file mode 100644 index 0000000..39e4755 --- /dev/null +++ b/.github/workflows/ci-disable-gtest.yml @@ -0,0 +1,63 @@ +# This is a copy of ci-unix-static.yml with gtest disabled. It differs from ci-unix-static.yml as follows: +# +# * The os matrix consists of ubuntu-24.04 only. +# * Does not build libgav1. (Building libgav1 would enable CXX in CMakeLists.txt.) +# * Disables gtest. + +name: CI Disable GTest +on: + push: + pull_request: + paths: + - '.github/workflows/ci-disable-gtest.yml' + - '**CMakeLists.txt' + - 'cmake/**' + - 'ext/**' + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-disable-gtest: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04] + include: + - runs-on: ubuntu-24.04 + compiler: gcc + gcc: 14 + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-linux + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + codec-rav1e: 'LOCAL' + gcc-version: ${{ matrix.gcc }} + libyuv: 'LOCAL' + recent-cmake: 'true' + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_DAV1D=LOCAL + -DAVIF_CODEC_RAV1E=LOCAL -DAVIF_CODEC_SVT=LOCAL + -DAVIF_LIBYUV=LOCAL -DAVIF_LIBSHARPYUV=LOCAL + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=OFF + -DAVIF_ENABLE_WERROR=ON + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $(getconf _NPROCESSORS_ONLN) --output-on-failure diff --git a/.github/workflows/ci-linux-golden-tests.yml b/.github/workflows/ci-linux-golden-tests.yml new file mode 100644 index 0000000..b028942 --- /dev/null +++ b/.github/workflows/ci-linux-golden-tests.yml @@ -0,0 +1,79 @@ +# Workflow that builds libabvif with aom and libyuv, also builds MP4box, +# and runs tests with "golden" in their name. Test results are saved as artifacts +# which can be downloaded from GitHub'S UI or with 'gh run download'. + +name: CI Linux Golden Tests +on: [push, pull_request] + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-shared-run-golden-tests: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04] + include: + - runs-on: ubuntu-24.04 + compiler: gcc + gcc: 14 + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-linux + id: setup + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + gcc-version: ${{ matrix.gcc }} + libxml2: 'LOCAL' + libyuv: 'LOCAL' + recent-cmake: 'true' + - name: Build mp4box + if: steps.setup.outputs.ext-cache-hit != 'true' + working-directory: ./ext + run: bash -e mp4box.sh + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=LOCAL -DAVIF_LIBYUV=LOCAL + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_ENABLE_EXPERIMENTAL_GAIN_MAP=ON + -DAVIF_LIBXML2=LOCAL + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GOLDEN_TESTS=ON + -DAVIF_ENABLE_GTEST=OFF -DAVIF_ENABLE_WERROR=ON + -DGOLDEN_TESTS_OUTPUT_DIR=${{ runner.temp }}/golden_tests + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF golden tests + working-directory: ./build + # Runs test that have "golden" in their name. + run: ctest -j $(getconf _NPROCESSORS_ONLN) --output-on-failure -R golden + + # See https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts + - name: Archive golden tests output for debugging + if: failure() + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + with: + name: golden-tests-output + path: ${{ runner.temp }}/golden_tests/**/* + + # Print instructions to help fix the tests. + - name: How to fix failing tests + if: failure() + run: > + echo "If the tests fail, download the test results from the Artifacts list at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} or with: + gh run download --dir /tmp/golden-tests-output-${{ github.run_id }} --repo ${{ github.repository }} --name golden-tests-output ${{ github.run_id }} + Update all files with: + cp /tmp/golden-tests-output-${{ github.run_id }}/*/*.xml ~/git/libavif/tests/data/goldens + Or look at detailed instructions in the README.txt file in the test ouputs." diff --git a/.github/workflows/ci-linux-static-old-local.yml b/.github/workflows/ci-linux-static-old-local.yml new file mode 100644 index 0000000..4d25be6 --- /dev/null +++ b/.github/workflows/ci-linux-static-old-local.yml @@ -0,0 +1,70 @@ +name: CI Unix Static For AVIF_LOCAL +on: + push: + pull_request: + paths: + - '.github/workflows/ci-linux-static-old-local.yml' + - '**CMakeLists.txt' + - 'cmake/**' + - 'ext/**' + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-static-old-local: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04] + include: + - runs-on: ubuntu-24.04 + compiler: gcc + gcc: 14 + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-linux + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + codec-rav1e: 'LOCAL' + gcc-version: ${{ matrix.gcc }} + libxml2: 'LOCAL' + libyuv: 'LOCAL' + recent-cmake: 'true' + - name: Prepare libavif (cmake) + run: > + cmake .. -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=ON -DAVIF_LOCAL_AOM=ON + -DAVIF_CODEC_DAV1D=ON -DAVIF_LOCAL_DAV1D=ON + -DAVIF_CODEC_RAV1E=ON -DAVIF_LOCAL_RAV1E=ON + -DAVIF_CODEC_SVT=ON -DAVIF_LOCAL_SVT=ON + -DAVIF_CODEC_LIBGAV1=ON -DAVIF_LOCAL_LIBGAV1=ON + -DAVIF_LOCAL_LIBSHARPYUV=ON -DAVIF_LOCAL_LIBXML2=ON -DAVIF_LOCAL_LIBYUV=ON + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_LOCAL_GTEST=ON + -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON + -DAVIF_ENABLE_EXPERIMENTAL_GAIN_MAP=ON + -DAVIF_ENABLE_EXPERIMENTAL_METAV1=ON + -DAVIF_ENABLE_WERROR=ON + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $(getconf _NPROCESSORS_ONLN) --output-on-failure + - name: Check static link bundling + run: | + cc -o avifenc -I./apps/shared -I./third_party/iccjpeg -I./include apps/avifenc.c \ + apps/shared/*.c third_party/iccjpeg/iccjpeg.c build/libavif.a \ + -lpng -ljpeg -lz -lm -ldl -lstdc++ + + ./avifenc --help diff --git a/.github/workflows/ci-mingw.yml b/.github/workflows/ci-mingw.yml new file mode 100644 index 0000000..7d910e2 --- /dev/null +++ b/.github/workflows/ci-mingw.yml @@ -0,0 +1,72 @@ +# This is a copy of ci-unix-shared-local.yml for building shared libraries +# with an additional build configuration (using installed deps and dav1d). + +name: CI MinGW +on: [push, pull_request] + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-mingw: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + sys: + - mingw64 + - ucrt64 + - clang64 + + defaults: + run: + shell: msys2 {0} + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.sys }} + update: true + install: >- + git + pacboy: >- + aom:p + cmake:p + diffutils:p + cc:p + dav1d:p + imagemagick:p + libjpeg-turbo:p + libpng:p + libyuv:p + ninja:p + zlib:p + - uses: ./.github/actions/cache + with: + extra-key: ${{ matrix.sys }} + - name: Print cmake version + run: cmake --version + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=SYSTEM + -DAVIF_CODEC_AOM_DECODE=OFF -DAVIF_CODEC_AOM_ENCODE=ON + -DAVIF_CODEC_DAV1D=SYSTEM + -DAVIF_LIBSHARPYUV=LOCAL -DAVIF_LIBYUV=SYSTEM + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL + -DAVIF_BUILD_GDK_PIXBUF=ON + -DAVIF_ENABLE_WERROR=ON + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j --output-on-failure diff --git a/.github/workflows/ci-unix-shared-installed.yml b/.github/workflows/ci-unix-shared-installed.yml new file mode 100644 index 0000000..961e997 --- /dev/null +++ b/.github/workflows/ci-unix-shared-installed.yml @@ -0,0 +1,97 @@ +# This is a copy of ci-unix-shared-local.yml for building shared libraries +# with an additional build configuration (using installed deps and dav1d). + +name: CI Unix Shared Installed +on: [push, pull_request] + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-shared-installed: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04, macos-latest] + include: + - runs-on: ubuntu-24.04 + compiler: gcc + gcc: 14 + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-linux + if: runner.os == 'Linux' + with: + codec-aom: 'SYSTEM' + codec-dav1d: 'SYSTEM' + gcc-version: ${{ matrix.gcc }} + gtest: 'SYSTEM' + libyuv: 'SYSTEM' + - uses: ./.github/actions/setup-macos + if: runner.os == 'macOS' + with: + codec-aom: 'SYSTEM' + codec-dav1d: 'SYSTEM' + gtest: 'SYSTEM' + - name: Disable libyuv on macOS + # TODO(yguyon): Install libyuv (not available with brew). + if: runner.os == 'macOS' + run: echo "CMAKE_AVIF_FLAGS=\"-DAVIF_LIBYUV=OFF\"" >> $GITHUB_ENV + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON + -DAVIF_CODEC_AOM=SYSTEM + -DAVIF_CODEC_AOM_DECODE=OFF -DAVIF_CODEC_AOM_ENCODE=ON + -DAVIF_CODEC_DAV1D=SYSTEM + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=SYSTEM + -DAVIF_BUILD_GDK_PIXBUF=ON -DCMAKE_INSTALL_PREFIX=./build/install + -DAVIF_ENABLE_WERROR=ON ${{ env.CMAKE_AVIF_FLAGS }} + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $(getconf _NPROCESSORS_ONLN) --output-on-failure + - name: Install AVIF + working-directory: ./build + run: ninja install + - name: Test installed cmake + working-directory: ./build + run: > + mkdir test && cd test + + echo "cmake_minimum_required(VERSION 3.13) + project(FindPackageTest) + message(STATUS ${CMAKE_PREFIX_PATH}) + find_package(libavif REQUIRED) + if(TARGET avif) + message(STATUS "\""avif found"\"") + else() + message(FATAL_ERROR "\""avif not found"\"") + endif()" >> CMakeLists.txt + + cmake . -DCMAKE_PREFIX_PATH=../install + - name: Prepare libavif with [[nodiscard]] (cmake) + run: > + cmake -G Ninja -S . -B build_nodiscard + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON + -DAVIF_CODEC_AOM=SYSTEM + -DAVIF_CODEC_AOM_DECODE=OFF -DAVIF_CODEC_AOM_ENCODE=ON + -DAVIF_CODEC_DAV1D=SYSTEM + -DAVIF_ENABLE_NODISCARD=ON -DAVIF_ENABLE_WERROR=ON + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL + -DAVIF_BUILD_GDK_PIXBUF=ON ${{ env.CMAKE_AVIF_FLAGS }} + - name: Build libavif with [[nodiscard]] (ninja) + working-directory: ./build_nodiscard + run: ninja diff --git a/.github/workflows/ci-unix-shared-local.yml b/.github/workflows/ci-unix-shared-local.yml new file mode 100644 index 0000000..f9aaf84 --- /dev/null +++ b/.github/workflows/ci-unix-shared-local.yml @@ -0,0 +1,68 @@ +# This is a copy of ci-unix-static.yml for building shared libraries. It differs from ci-unix-static.yml as follows: +# +# * The os matrix consists of ubuntu-24.04 only. +# * Does not build rav1e, SVT-AV1 nor libgav1. + +name: CI Unix Shared Local +on: [push, pull_request] + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-shared-local: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04, macos-13] + libyuv: [OFF, LOCAL] + include: + - runs-on: ubuntu-24.04 + compiler: gcc + gcc: 14 + + name: build-shared-local (${{ matrix.os }}, libyuv ${{ matrix.libyuv }}) + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-linux + if: runner.os == 'Linux' + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + gcc-version: ${{ matrix.gcc }} + libxml2: 'LOCAL' + libyuv: ${{ matrix.libyuv }} + recent-cmake: 'true' + - uses: ./.github/actions/setup-macos + if: runner.os == 'macOS' + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON + -DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_DAV1D=LOCAL + -DAVIF_LIBSHARPYUV=LOCAL -DAVIF_LIBXML2=LOCAL + -DAVIF_LIBYUV=${{ matrix.libyuv }} + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL + -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON + -DAVIF_ENABLE_EXPERIMENTAL_GAIN_MAP=ON + -DAVIF_ENABLE_EXPERIMENTAL_METAV1=ON + -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON + -DAVIF_ENABLE_WERROR=ON + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $(getconf _NPROCESSORS_ONLN) --output-on-failure diff --git a/.github/workflows/ci-unix-static-av2.yml b/.github/workflows/ci-unix-static-av2.yml new file mode 100644 index 0000000..cb7d169 --- /dev/null +++ b/.github/workflows/ci-unix-static-av2.yml @@ -0,0 +1,68 @@ +name: CI Unix Static AV2 +on: + push: + pull_request: + paths: + - '.github/workflows/ci-unix-static-av2.yml' + - '**CMakeLists.txt' + - 'cmake/**' + - 'ext/**' + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-static-av2: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + also-enable-av1-codecs: [OFF, LOCAL] # On top of enabling AV2 codecs. + include: + - runs-on: ubuntu-24.04 + compiler: gcc + gcc: 14 + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-linux + with: + codec-aom: 'LOCAL' + codec-dav1d: ${{ matrix.also-enable-av1-codecs }} + codec-rav1e: ${{ matrix.also-enable-av1-codecs }} + extra-cache-key: ${{ matrix.also-enable-av1-codecs }} + gcc-version: ${{ matrix.gcc }} + libyuv: 'LOCAL' + recent-cmake: 'true' + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AVM=LOCAL + -DAVIF_CODEC_DAV1D=${{ matrix.also-enable-av1-codecs }} + -DAVIF_CODEC_RAV1E=${{ matrix.also-enable-av1-codecs }} + -DAVIF_CODEC_SVT=${{ matrix.also-enable-av1-codecs }} + -DAVIF_LIBYUV=LOCAL + -DAVIF_LIBSHARPYUV=LOCAL + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL + -DAVIF_ENABLE_WERROR=ON + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $(getconf _NPROCESSORS_ONLN) --output-on-failure + - name: Check static link bundling + run: | + cc -o avifenc -I./apps/shared -I./third_party/iccjpeg -I./include apps/avifenc.c \ + apps/shared/*.c third_party/iccjpeg/iccjpeg.c build/libavif.a \ + -lpng -ljpeg -lz -lm -ldl -lstdc++ + + ./avifenc --help diff --git a/.github/workflows/ci-unix-static-sanitized.yml b/.github/workflows/ci-unix-static-sanitized.yml new file mode 100644 index 0000000..08c223d --- /dev/null +++ b/.github/workflows/ci-unix-static-sanitized.yml @@ -0,0 +1,104 @@ +name: CI Unix Static Sanitized +on: + push: + pull_request: + paths: + - '.github/workflows/ci-unix-static-sanitized.yml' + - '**CMakeLists.txt' + - 'cmake/**' + - 'ext/**' + +permissions: + contents: read + +jobs: + build-static-sanitized: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + sanitizer: [ address, thread, undefined ] # TODO(yguyon): Add memory + + env: + CC: clang + CXX: clang++ + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-linux + if: runner.os == 'Linux' + id: setup_linux + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + libyuv: 'LOCAL' + recent-cmake: 'true' + extra-cache-key: ${{ matrix.sanitizer }} + - uses: ./.github/actions/setup-macos + if: runner.os == 'macOS' + id: setup_macos + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + extra-cache-key: ${{ matrix.sanitizer }} + - id: cache-hit + run: echo "hit=${{ (runner.os == 'Linux' && steps.setup_linux.outputs.ext-cache-hit == 'true') || (runner.os == 'macOS' && steps.setup_macos.outputs.ext-cache-hit == 'true') }}" >> "$GITHUB_OUTPUT" + + - name: Build aom + if: ${{ steps.cache-hit.outputs.hit == 'false' }} + working-directory: ./ext + run: > + sed -i -e 's/cmake -G Ninja \(.*\) \.\./cmake -G Ninja \1 -DSANITIZE=${{ matrix.sanitizer }} ../g' aom.cmd + + ./aom.cmd + - name: Build dav1d + if: ${{ steps.cache-hit.outputs.hit == 'false' }} + working-directory: ./ext + run: > + sed -i -e 's/meson setup \(.*\) \.\./meson setup \1 -Db_sanitize=${{ matrix.sanitizer }} -Db_lundef=false ../g' dav1d.cmd + + ./dav1d.cmd + - name: Build libyuv + if: ${{ steps.cache-hit.outputs.hit == 'false' }} + working-directory: ./ext + run: ./libyuv.cmd + env: + CFLAGS: -fsanitize=${{ matrix.sanitizer }} + CXXFLAGS: -fsanitize=${{ matrix.sanitizer }} + LDFLAGS: -fsanitize=${{ matrix.sanitizer }} + - name: Build libsharpyuv + if: ${{ steps.cache-hit.outputs.hit == 'false' }} + working-directory: ./ext + run: ./libsharpyuv.cmd + env: + CFLAGS: -fsanitize=${{ matrix.sanitizer }} + CXXFLAGS: -fsanitize=${{ matrix.sanitizer }} + LDFLAGS: -fsanitize=${{ matrix.sanitizer }} + - name: Build GoogleTest + if: ${{ steps.cache-hit.outputs.hit == 'false' }} + working-directory: ./ext + # Note: "apt install googletest" is sometimes insufficient for find_package(GTest) so build in ext/ instead. + run: bash -e googletest.cmd + + - name: Prepare libavif (cmake) + run: > + cmake -S . -B build -G Ninja + -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_DAV1D=LOCAL + -DAVIF_LIBYUV=LOCAL -DAVIF_LIBSHARPYUV=LOCAL + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL + env: + CFLAGS: -fsanitize=${{ matrix.sanitizer }} + CXXFLAGS: -fsanitize=${{ matrix.sanitizer }} + LDFLAGS: -fsanitize=${{ matrix.sanitizer }} + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $(getconf _NPROCESSORS_ONLN) --output-on-failure + env: + ASAN_OPTIONS: allocator_may_return_null=1 + TSAN_OPTIONS: allocator_may_return_null=1 diff --git a/.github/workflows/ci-unix-static.yml b/.github/workflows/ci-unix-static.yml new file mode 100644 index 0000000..1ced56f --- /dev/null +++ b/.github/workflows/ci-unix-static.yml @@ -0,0 +1,79 @@ +name: CI Unix Static +on: + push: + pull_request: + paths: + - '.github/workflows/ci-unix-static.yml' + - '**CMakeLists.txt' + - 'cmake/**' + - 'ext/**' + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-static: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04, macos-13] + build-type: [Release, Debug] + include: + - runs-on: ubuntu-24.04 + compiler: gcc + gcc: 14 + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-linux + if: runner.os == 'Linux' + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + codec-rav1e: 'LOCAL' + gcc-version: ${{ matrix.gcc }} + libxml2: 'LOCAL' + libyuv: 'LOCAL' + recent-cmake: 'true' + - uses: ./.github/actions/setup-macos + if: runner.os == 'macOS' + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + codec-rav1e: 'LOCAL' + extra-cache-key: ${{ matrix.build-type }} + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_DAV1D=LOCAL + -DAVIF_CODEC_RAV1E=LOCAL -DAVIF_CODEC_SVT=LOCAL + -DAVIF_CODEC_LIBGAV1=LOCAL + -DAVIF_LIBSHARPYUV=LOCAL -DAVIF_LIBXML2=LOCAL -DAVIF_LIBYUV=LOCAL + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL + -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON + -DAVIF_ENABLE_EXPERIMENTAL_GAIN_MAP=ON + -DAVIF_ENABLE_EXPERIMENTAL_METAV1=ON + -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON + -DAVIF_ENABLE_WERROR=ON + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $(getconf _NPROCESSORS_ONLN) --output-on-failure + - name: Check static link bundling + run: | + cc -o avifenc -I./apps/shared -I./third_party/iccjpeg -I./include apps/avifenc.c \ + apps/shared/*.c third_party/iccjpeg/iccjpeg.c build/libavif.a \ + -lpng -ljpeg -lz -lm -ldl -lstdc++ + + ./avifenc --help diff --git a/.github/workflows/ci-windows-artifacts.yml b/.github/workflows/ci-windows-artifacts.yml new file mode 100644 index 0000000..657ecd9 --- /dev/null +++ b/.github/workflows/ci-windows-artifacts.yml @@ -0,0 +1,86 @@ +# This workflow generates artifacts such as avifenc.exe and avifdec.exe for convenience. + +name: CI Windows Artifacts +on: + release: + types: [created] + +permissions: + contents: write + +jobs: + build-windows-artifacts: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-latest] + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-windows + id: setup + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + + - name: Build aom + if: steps.setup.outputs.ext-cache-hit != 'true' + working-directory: ./ext + run: ./aom.cmd + - name: Build dav1d + if: steps.setup.outputs.ext-cache-hit != 'true' + working-directory: ./ext + run: ./dav1d.cmd + - name: Build libyuv + if: steps.setup.outputs.ext-cache-hit != 'true' + working-directory: ./ext + run: ./libyuv.cmd + # Use clang-cl to build libyuv. The assembly code in libyuv is written in the + # GCC inline assembly format. Visual C++ doesn't support GCC inline assembly. + env: + CC: clang-cl + CXX: clang-cl + - name: Build libsharpyuv + if: steps.setup.outputs.ext-cache-hit != 'true' + working-directory: ./ext + run: ./libsharpyuv.cmd + - name: Build libjpeg + if: steps.setup.outputs.ext-cache-hit != 'true' + working-directory: ./ext + run: ./libjpeg.cmd + - name: Build zlib and libpng + if: steps.setup.outputs.ext-cache-hit != 'true' + working-directory: ./ext + run: ./zlibpng.cmd + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_AOM_ENCODE=ON + -DAVIF_CODEC_AOM_DECODE=OFF -DAVIF_CODEC_DAV1D=LOCAL + -DAVIF_LIBYUV=LOCAL -DAVIF_LIBSHARPYUV=LOCAL + -DAVIF_JPEG=LOCAL -DAVIF_ZLIBPNG=LOCAL + -DAVIF_BUILD_EXAMPLES=OFF -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=OFF -DAVIF_ENABLE_WERROR=ON + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Archive artifacts + uses: thedoctor0/zip-release@b57d897cb5d60cb78b51a507f63fa184cfe35554 # 0.7.6 + with: + type: 'zip' + filename: 'windows-artifacts.zip' + directory: 'build' + path: '*.exe' + - name: Upload artifacts + uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5 # v1.0.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # See https://docs.github.com/en/webhooks/webhook-events-and-payloads#release. + upload_url: ${{ github.event.release.upload_url }} + asset_path: build/windows-artifacts.zip + asset_name: windows-artifacts.zip + asset_content_type: application/zip diff --git a/.github/workflows/ci-windows-installed.yml b/.github/workflows/ci-windows-installed.yml new file mode 100644 index 0000000..0c6200b --- /dev/null +++ b/.github/workflows/ci-windows-installed.yml @@ -0,0 +1,86 @@ +# This is a copy of ci-windows.yml for installed dependencies. It differs in the following ways: +# +# * vcpkg is used to install dependencies that are packaged. +# * rav1e is installed from a binary upstream. +# * TODO: use proper installations of libgav1, libsharpyuv and SVT once released. + +name: CI Windows Installed +on: [push, pull_request] + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-windows-installed: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + compiler: [msvc, clang-cl] + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-windows + with: + codec-aom: 'SYSTEM' + codec-dav1d: 'SYSTEM' + codec-rav1e: 'SYSTEM' + extra-cache-key: ${{ matrix.compiler }} + - name: Leave compiler as default + if: matrix.compiler == 'msvc' + run: | + echo "AVIF_CMAKE_C_COMPILER=" >> $env:GITHUB_ENV + echo "AVIF_CMAKE_CXX_COMPILER=" >> $env:GITHUB_ENV + - name: Set clang-cl as compiler + if: matrix.compiler == 'clang-cl' + run: | + echo "AVIF_CMAKE_C_COMPILER=-DCMAKE_C_COMPILER=clang-cl" >> $env:GITHUB_ENV + echo "AVIF_CMAKE_CXX_COMPILER=-DCMAKE_CXX_COMPILER=clang-cl" >> $env:GITHUB_ENV + + - name: vcpkg build + uses: johnwason/vcpkg-action@v6 + id: vcpkg + with: + pkgs: aom dav1d libjpeg-turbo libpng libxml2 libyuv zlib + triplet: x64-windows-release + token: ${{ github.token }} + github-binarycache: true + cache-key: ${{ hashFiles('cmake/Modules/*', 'ext/*.cmd', 'ext/*.sh') }} + - name: Install rav1e + run: | + $LINK = "https://github.com/xiph/rav1e/releases/download/v0.7.1" + $FILE = "rav1e-0.7.1-windows-msvc-generic" + curl -LO "$LINK/$FILE.zip" + mkdir -p ${{ github.workspace }}\tmp + 7z x -y "$FILE.zip" -o"${{ github.workspace }}\tmp" + # Do not mv the folder's content to not overwrite, and rsync is not installed. + mv ${{ github.workspace }}\tmp\rav1e-windows-msvc-sdk\bin\* ${{ github.workspace }}\vcpkg\installed\x64-windows-release\bin + mv ${{ github.workspace }}\tmp\rav1e-windows-msvc-sdk\include\* ${{ github.workspace }}\vcpkg\installed\x64-windows-release\include + mv ${{ github.workspace }}\tmp\rav1e-windows-msvc-sdk\lib\rav1e* ${{ github.workspace }}\vcpkg\installed\x64-windows-release\lib + mv ${{ github.workspace }}\tmp\rav1e-windows-msvc-sdk\lib\pkgconfig\* ${{ github.workspace }}\vcpkg\installed\x64-windows-release\lib\pkgconfig + - name: Prepare libavif (cmake) + run: > + cmake ${{ steps.vcpkg.outputs.vcpkg-cmake-config }} -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=SYSTEM -DAVIF_CODEC_DAV1D=SYSTEM + -DAVIF_CODEC_RAV1E=SYSTEM + -DAVIF_JPEG=SYSTEM -DAVIF_LIBXML2=SYSTEM + -DAVIF_LIBYUV=SYSTEM -DAVIF_ZLIBPNG=SYSTEM + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL + -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON + -DAVIF_ENABLE_EXPERIMENTAL_GAIN_MAP=ON + -DAVIF_ENABLE_EXPERIMENTAL_METAV1=ON + -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON + -DAVIF_ENABLE_WERROR=ON $env:AVIF_CMAKE_C_COMPILER $env:AVIF_CMAKE_CXX_COMPILER + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $Env:NUMBER_OF_PROCESSORS --output-on-failure diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml new file mode 100644 index 0000000..173a0fe --- /dev/null +++ b/.github/workflows/ci-windows.yml @@ -0,0 +1,100 @@ +# This is a copy of ci-unix-static.yml for Windows. It differs from ci-unix-static.yml as follows: +# +# * The os matrix consists of windows-latest only. +# * Installs Visual Studio in the os image. +# * Doesn't install cmake 3.17.x, because only cmake 3.18 or later, with the +# following bug fix, detects Visual Studio compilers correctly: +# https://gitlab.kitware.com/cmake/cmake/-/issues/20585 +# * Runs ext/*.cmd as Windows batch files rather than using bash. This is +# important for ext/svt.cmd, to prevent it from running ext/svt.sh. +# * Builds with local libjpeg (-DAVIF_JPEG=LOCAL). +# * Builds with local zlib and libpng (-DAVIF_ZLIBPNG=LOCAL). + +name: CI Windows +on: + push: + pull_request: + paths: + - '.github/workflows/ci-windows.yml' + - '**CMakeLists.txt' + - 'cmake/**' + - 'ext/**' + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build-windows: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-latest] + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: ./.github/actions/setup-windows + id: setup + with: + codec-aom: 'LOCAL' + codec-dav1d: 'LOCAL' + codec-rav1e: 'LOCAL' + + - name: Build libyuv + if: steps.setup.outputs.ext-cache-hit != 'true' + working-directory: ./ext + run: ./libyuv.cmd + # Use clang-cl to build libyuv. The assembly code in libyuv is written in the + # GCC inline assembly format. Visual C++ doesn't support GCC inline assembly. + env: + CC: clang-cl + CXX: clang-cl + + - name: Prepare libavif (cmake) + run: > + cmake -G Ninja -S . -B build + -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + -DAVIF_CODEC_AOM=LOCAL -DAVIF_CODEC_DAV1D=LOCAL + -DAVIF_CODEC_RAV1E=LOCAL -DAVIF_CODEC_SVT=LOCAL + -DAVIF_CODEC_LIBGAV1=LOCAL + -DAVIF_JPEG=LOCAL -DAVIF_LIBSHARPYUV=LOCAL -DAVIF_LIBXML2=LOCAL + -DAVIF_LIBYUV=LOCAL -DAVIF_ZLIBPNG=LOCAL + -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON + -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL + -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON + -DAVIF_ENABLE_EXPERIMENTAL_GAIN_MAP=ON + -DAVIF_ENABLE_EXPERIMENTAL_METAV1=ON + -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON + -DAVIF_ENABLE_WERROR=ON + - name: Build libavif (ninja) + working-directory: ./build + run: ninja + - name: Run AVIF Tests + working-directory: ./build + run: ctest -j $Env:NUMBER_OF_PROCESSORS --output-on-failure + - name: Check static link bundling + run: > + cl .\apps\avifenc.c .\apps\shared\*.c .\third_party\iccjpeg\iccjpeg.c /nologo + /DWIN32 /D_WINDOWS /MD /O2 /Ob2 + -I.\apps\shared -I.\include -I.\third_party\iccjpeg + -external:W0 + -external:I.\build\_deps\libpng-src + -external:I.\build\libjpeg\src\libjpeg + -external:I.\build\libjpeg\src\libjpeg-build + -external:I.\build\_deps\zlib-src + -external:I.\build\_deps\libpng + -external:I.\build\_deps\zlib + /link + build\libjpeg\src\libjpeg-build\jpeg-static.lib + build\_deps\libpng\libpng16_static.lib + build\_deps\zlib\zlibstatic.lib + build\avif.lib + ws2_32.lib ntdll.lib userenv.lib bcrypt.lib advapi32.lib + /out:avifenc.exe + + .\avifenc.exe --help diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml new file mode 100644 index 0000000..56371f7 --- /dev/null +++ b/.github/workflows/cifuzz.yml @@ -0,0 +1,41 @@ +name: CI Fuzz +on: + push: + pull_request: + paths: + - '.github/workflows/cifuzz.yml' + - 'cmake/**' + - 'ext/**' + - 'tests/gtest/**' + - 'tests/oss-fuzz/**' + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + fuzz: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'libavif' + dry-run: false + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'libavif' + fuzz-seconds: 600 + dry-run: false + - name: Upload Crash + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + if: failure() && steps.build.outcome == 'success' + with: + name: artifacts + path: ./out/artifacts diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml new file mode 100644 index 0000000..94aa8ef --- /dev/null +++ b/.github/workflows/clang-format-check.yml @@ -0,0 +1,21 @@ +name: CI Format Check +on: [push, pull_request] + +permissions: + contents: read + +# Cancel the workflow if a new one is triggered from the same PR, branch, or tag, except on main. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + clang-format-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: RafikFarhad/clang-format-github-action@873e2c426db342189305bc04213fe55cb701fd91 # v4 + with: + style: file + sources: "apps/*.c,apps/**/*.h,apps/**/*.c,apps/**/*.cc,examples/*.c,include/avif/*.h,src/*.c,tests/*.c,tests/**/*.h,tests/**/*.cc" + excludes: "apps/shared/iccjpeg.h,apps/shared/iccjpeg.c" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..5d7b321 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,65 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '37 5 * * 3' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results (see publish_results below). + id-token: write + + steps: + - name: "Checkout code" + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if + # you want to enable the Branch-Protection check on a *public* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 + with: + sarif_file: results.sarif diff --git a/.gitignore b/.gitignore index 90b5532..797db2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,24 @@ /build* /obj* /ext/aom +/ext/avm +/ext/ComplianceWarden /ext/dav1d +/ext/fuzztest +/ext/googletest +/ext/gpac +/ext/libargparse /ext/libjpeg +/ext/libjpeg-turbo /ext/libgav1 /ext/libpng +/ext/libwebp +/ext/libxml2 /ext/libyuv /ext/rav1e /ext/SVT-AV1 /ext/zlib .clangd/ +.vscode/ cscope.* tags diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29..0000000 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9aecfaa..0000000 --- a/.travis.yml +++ /dev/null @@ -1,86 +0,0 @@ -language: c -os: linux -dist: focal - -addons: - apt: - packages: - - ninja-build - - python3 - - python3-pip - -before_script: - - curl -L https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.gz | tar xvz - - cd nasm-2.15.05 - - ./configure && make -j2 && sudo make install - - nasm --version - - pip3 --disable-pip-version-check install setuptools - - pip3 --disable-pip-version-check install meson - - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - source $HOME/.cargo/env - - cd $TRAVIS_BUILD_DIR/ext - - export MAKEFLAGS=-j$(nproc) - - bash aom.cmd - - bash dav1d.cmd - - bash libgav1.cmd - - bash rav1e.cmd - - bash svt.cmd - - bash libyuv.cmd - - cd .. - - mkdir build - - cd build -script: - - cmake -G Ninja -DCMAKE_BUILD_TYPE=$config -DBUILD_SHARED_LIBS=OFF -DAVIF_CODEC_AOM=ON -DAVIF_LOCAL_AOM=ON -DAVIF_CODEC_DAV1D=ON -DAVIF_LOCAL_DAV1D=ON -DAVIF_CODEC_RAV1E=ON -DAVIF_LOCAL_RAV1E=ON -DAVIF_CODEC_LIBGAV1=ON -DAVIF_LOCAL_LIBGAV1=ON -DAVIF_CODEC_SVT=ON -DAVIF_LOCAL_SVT=ON -DAVIF_LOCAL_LIBYUV=ON -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON .. - - ninja - -matrix: - include: - - name: "GCC Debug" - compiler: gcc - config: Debug - - name: "GCC Release" - compiler: gcc - config: Release - - name: "Clang Debug" - compiler: clang - config: Debug - - name: "Clang Debug (aom decode only)" - compiler: clang - config: Debug - script: - - cmake -G Ninja -DCMAKE_BUILD_TYPE=$config -DBUILD_SHARED_LIBS=OFF -DAVIF_CODEC_AOM=ON -DAVIF_LOCAL_AOM=ON -DAVIF_CODEC_AOM_ENCODE=0 -DAVIF_BUILD_APPS=ON .. - - ninja - - name: "Clang Debug (aom encode only)" - compiler: clang - config: Debug - script: - - cmake -G Ninja -DCMAKE_BUILD_TYPE=$config -DBUILD_SHARED_LIBS=OFF -DAVIF_CODEC_AOM=ON -DAVIF_LOCAL_AOM=ON -DAVIF_CODEC_AOM_DECODE=0 -DAVIF_BUILD_APPS=ON .. - - ninja - - name: "Clang Release" - compiler: clang - config: Release - - &freebsd_common - name: "Clang 10 + system libraries" - os: freebsd - compiler: clang - before_install: - - | # FreeBSD 12.2 has Clang 10 but TravisCI uses FreeBSD 12.1 - if [[ $(${CC:-clang} --version) =~ 8.0 ]]; then - export CC=clang10 CXX=clang++10 - sudo pkg install -y llvm10 - fi - before_script: - - sudo pkg install -y aom dav1d libgav1 librav1e ninja - - $WRAPPER cmake -B build -G Ninja -DAVIF_{CODEC_{AOM,DAV1D,LIBGAV1,RAV1E},BUILD_{APPS,TESTS}}=ON - script: - - $WRAPPER cmake --build build - - <<: *freebsd_common - name: "GCC 10 + system libraries" - compiler: gcc - before_install: - - sudo pkg upgrade -y gcc10-devel - - <<: *freebsd_common - name: "Clang Static Analyzer" - env: WRAPPER="scan-build11 --status-bugs" - before_install: - - sudo pkg install -y llvm11 diff --git a/CHANGELOG.md b/CHANGELOG.md index 38e32be..3502ac9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,567 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +The changes are relative to the previous release, unless the baseline is specified. + ## [Unreleased] +## [1.1.1] - 2024-07-30 + +### Changed since 1.1.0 +* In avif.h, change "AVIF_API AVIF_NODISCARD" back to "AVIF_NODISCARD AVIF_API" + to fix clang-cl and MSVC compilation errors in the shared library build on + Windows. +* Fix -DAVIF_GTEST=SYSTEM, https://github.com/AOMediaCodec/libavif/issues/2258. +* Fix infe_type and codec_config_type wrongly read as byte-aligned fields in the + experimental feature AVIF_ENABLE_EXPERIMENTAL_METAV1. +* When building aom as a local dependency, runtime CPU detection + (`CONFIG_RUNTIME_CPU_DETECT`) is now always `ON`; in 1.1.0 it had been + disabled for non-native builds. +* Fix CMake config shared library leaks + https://github.com/AOMediaCodec/libavif/issues/2264. +* Fix clang-cl compilation. +* Update gain map metadata to current ISO 21496-1 draft. +* cmake: Only search for ASM_NASM language on x86_64 platforms. +* Fix "No known features for CXX compiler" CMake error. +* Fix aom link flags so that transitive library link flags are included when + aom is a static library + https://github.com/AOMediaCodec/libavif/issues/2274. +* Fix out-of-order 'dimg' grid associations + https://github.com/AOMediaCodec/libavif/issues/2311. +* Report files with an item used in multiple 'dimg' boxes with + AVIF_RESULT_NOT_IMPLEMENTED instead of AVIF_RESULT_INVALID_IMAGE_GRID. + +## [1.1.0] - 2024-07-11 + +### Added since 1.0.0 +* Add experimental API for reading and writing gain maps in AVIF files. + If enabled at compile time, add `gainMap` field to `avifImage`, + add `qualityGainMap` field to `avifEncoder`, add `gainMapPresent`, + `enableDecodingGainMap`, `enableParsingGainMapMetadata` and + `ignoreColorAndAlpha` to `avifDecoder`. + Utility functions for working with gain maps are also added. + Gain maps allow readers that support them to display HDR images that look + good on both HDR and SDR displays. + This feature is highly experimental. The API might change or be removed + in the future. Files created now might not decode in a future version. + This feature is off by default and must be enabled with the + AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP compilation flag. +* Add experimental support for converting jpeg files with gain maps to AVIF + files with gain maps. Requires libxml2, and the AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP + compilation flag. + Add a --qgain-map flag to control the gain map quality in avifenc. +* Add the headerFormat member of new type avifHeaderFormat to avifEncoder. +* Add experimental API for reading and writing "mif3"-branded AVIF files + behind the compilation flag AVIF_ENABLE_EXPERIMENTAL_METAV1. +* Implement avifImageScale() fallback when libyuv is not available. +* Partial import of libyuv to third_party/libyuv (new LICENSE). +* Add avifenc flag suffixes ":update" and ":u". Quality-relative, + tiling-relative and codec-specific flags can now be positional, relative to + input files. +* Add experimental support for layered AVIF encoding in avifenc. + Use the --layered flag to enable layered AVIF encoding. + Layered AVIF has multiple layers, which works like frame of animated AVIF, + and layers can be rendered in progressive manner on supported viewers + (e.g. Chrome 94 or newer). + Only aom supports layered AVIF encoding at the time of writing. + Add --scaling-mode flag to set scaling mode of each layer. + This part of AV1 encoder is not as thoroughly tested, so there are higher + possibility encoder may crash when given certain configuration or input. +* Add imageSequenceTrackPresent flag to the avifDecoder struct. +* avifImageScale() function was made part of the public ABI. +* Add avif_cxx.h as a C++ header with basic functionality. +* Add enum aliases AVIF_COLOR_PRIMARIES_SRGB, AVIF_COLOR_PRIMARIES_BT2100, + AVIF_COLOR_PRIMARIES_DCI_P3, AVIF_TRANSFER_CHARACTERISTICS_PQ. +* Add avifResult enum entry AVIF_RESULT_INTERNAL_ERROR. +* Require libyuv by default (but it can still be disabled with + -DAVIF_LIBYUV=OFF). +* Add avifdec --icc flag to override the output color profile. +* Add experimental API for reading and writing 16-bit AVIF files behind the + compilation flag AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM. +* Add AVIF_CHROMA_SAMPLE_POSITION_RESERVED to avifChromaSamplePosition enum. + +### Changed since 1.0.0 +* Update aom.cmd: v3.9.1 +* Update avm.cmd: research-v7.0.1 +* Update dav1d.cmd: 1.4.3 +* Update libgav1.cmd: v0.19.0 +* Update libjpeg.cmd: v3.0.3 +* Update libxml2.cmd: v2.12.7 +* Update libyuv.cmd: a6a2ec65 +* Update mp4box.sh: v2.4.0 +* Update rav1e.cmd: v0.7.1 +* Update svt.cmd/svt.sh: v2.1.1 +* Update zlibpng.cmd: zlib 1.3.1 and libpng 1.6.40 +* AVIF sequences encoded by libavif will now also have the "avio" brand when + there is at least one track made only of AV1 keyframes. +* Fix SVT-AV1 codec interface which was not setting video range at encoding. +* Any item ID being 0 in an "iref" box with version 0 or 1 is now treated as an + error instead of being ignored. +* API calls now return AVIF_RESULT_OUT_OF_MEMORY instead of aborting on memory + allocation failure. +* avifdec and avifenc: Change the default value of the --jobs option from 1 to + "all". +* Update avifCropRectConvertCleanApertureBox() to the revised requirements in + ISO/IEC 23000-22:2019/Amd. 2:2021 Section 7.3.6.7. +* AVIF files with an exif_tiff_header_offset pointing at another byte than the + first II or MM tag in the Exif metadata payload will now fail to be decoded. + Set decoder->ignoreExif to true to skip the issue and decode the image. +* Fix memory errors reported in crbug.com/1501766, crbug.com/1501770, and + crbug.com/1504792 by [Fudan University](https://secsys.fudan.edu.cn/). +* For codecs, AVIF_CODEC_* and AVIF_LOCAL_* are now merged into AVIF_CODEC_* + that can only take the values: OFF, LOCAL or SYSTEM. +* For the gtest, jpeg, libsharpyuv, libxml2, libyuv and zlibpng dependencies, + AVIF_LOCAL_* is now replaced by flags AVIF_* that can take the values: + OFF, LOCAL or SYSTEM. +* src/reformat.c: Allocate the threadData array directly. +* AVIF_ENABLE_WERROR is set to OFF by default. +* Fix wrong alpha plane deallocation when decoded tile pixel format does not + match reconstructed output image pixel format (b/320234262). +* Fix identical chunk skipping optimization when writing animation data + (b/321189607). +* Fix ID selection for artificial grid alpha item when decoding a grid of tiles + which each have an associated auxiliary alpha image item + (https://crbug.com/oss-fuzz/65657). +* ext/libjpeg.cmd now pulls libjpeg-turbo instead of libjpeg and AVIF_JPEG=LOCAL + now expects the library dependency in ext/libjpeg-turbo/build.libavif. +* Fix 'iloc' box parsing bugs that may have wrongly accepted, rejected or parsed + some files with rare values of offset_size, length_size, base_offset_size and + index_size. +* 'infe' boxes with an item_type different from 'mime' and without a + null-terminated item_name are now considered invalid as per ISO/IEC 14496-12. + +## [1.0.4] - 2024-02-08 + +### Changed +* AVIF_ENABLE_WERROR is set to OFF by default. +* Fix wrong alpha plane deallocation when decoded tile pixel format does not + match reconstructed output image pixel format (b/320234262). +* Fix identical chunk skipping optimization when writing animation data + (b/321189607). +* Fix ID selection for artificial grid alpha item when decoding a grid of tiles + which each have an associated auxiliary alpha image item + (https://crbug.com/oss-fuzz/65657). + +## [1.0.3] - 2023-12-03 + +### Changed +* Rewrite the fix for memory errors reported in crbug.com/1501770. +* Fix memory errors reported in crbug.com/1504792 by [Fudan + University](https://secsys.fudan.edu.cn/). +* src/reformat.c: Allocate the threadData array directly. + +## [1.0.2] - 2023-11-16 + +### Changed +* Update avifCropRectConvertCleanApertureBox() to the revised requirements in + ISO/IEC 23000-22:2019/Amd. 2:2021 Section 7.3.6.7. +* Fix memory errors reported in crbug.com/1501766 and crbug.com/1501770 by + [Fudan University](https://secsys.fudan.edu.cn/). + +## [1.0.1] - 2023-08-29 + +### Changed +* gdk-pixbuf: Explicitly pass link directories +* gdk-pixbuf: Fix build failure after imir.mode -> imir.axis rename + +## [1.0.0] - 2023-08-24 + +With the 1.0.0 release, the ABI will be more stable from now on. Please note +the allocation and initialization requirements for avifImage, avifDecoder, +avifEncoder, and avifRGBImage in the "avif/avif.h" header. + +List of incompatible ABI changes in this release: + +* The clli member was added to the avifImage struct. +* The repetitionCount member was added to the avifEncoder and avifDecoder + structs. +* The quality and qualityAlpha members were added to the avifEncoder struct. +* Check that functions returning pointers do not return NULL before accessing + those pointers. +* Check the return value of avifEncoderSetCodecSpecificOption(). +* The maxThreads member was added to the avifRGBImage struct. +* Check the return value of avifRGBImageAllocatePixels(), avifRWDataRealloc(), + avifRWDataSet(), avifImageSetProfileICC(), avifImageSetMetadataExif() and + avifImageSetMetadataXMP(). +* The meaning of the keyframeInterval member of avifEncoder struct has changed + slightly. When set to a value of "n", + * Before: It forces a keyframe on every nth frame. + * After: Any set of "n" consecutive frame will have at least one keyframe + (every nth frame may or may not be a keyframe). + +### Added +* Add STATIC library target avif_internal to allow tests to access functions + from internal.h when BUILD_SHARED_LIBS is ON. +* Add clli metadata read and write support +* Add repetitionCount member to avifEncoder and avifDecoder structs to specify + the number of repetitions for animated image sequences. +* Add quality and qualityAlpha to avifEncoder. Note: minQuantizer, + maxQuantizer, minQuantizerAlpha, and maxQuantizerAlpha are deprecated. Code + should be updated to set quality (and qualityAlpha if applicable) and leave + minQuantizer, maxQuantizer, minQuantizerAlpha, and maxQuantizerAlpha + initialized to the default values. +* The --target-size flag in avifenc was added to adapt the quality so that the + output file size is as close to the given number of bytes as possible. +* Add the public API function avifImageIsOpaque() in avif.h. +* Add the public API functions avifImagePlane(), avifImagePlaneRowBytes(), + avifImagePlaneWidth(), and avifImagePlaneHeight() in avif.h. +* Add experimental API for progressive AVIF encoding. +* Add API for multi-threaded YUV to RGB color conversion. +* Add experimental support for AV2 behind the compilation flag AVIF_CODEC_AVM. + AVIF_CODEC_CHOICE_AVM is now part of avifCodecChoice. +* Add experimental YCgCo-R support behind the compilation flag + AVIF_ENABLE_EXPERIMENTAL_YCGCO_R. +* Allow lossless 4:0:0 on grayscale input. +* Add avifenc --no-overwrite flag to avoid overwriting output file. +* Add avifenc --clli flag to set clli. +* Add support for all transfer functions when using libsharpyuv. + +### Changed +* Enable the libaom AV1E_SET_SKIP_POSTPROC_FILTERING codec control by default. +* Use the constant rate factor (CRF) instead of the constant quantization + parameter (CQP) rate control mode with the SVT-AV1 encoder. +* Exif and XMP metadata is exported to PNG and JPEG files by default, + except XMP payloads larger than 65502 bytes in JPEG. +* The --grid flag in avifenc can be used for images that are not evenly divided + into cells. +* Apps must be built with libpng version 1.6.32 or above. +* Change the encoder to write the boxes within the "stbl" box in the order of + stsd, stts, stsc, stsz, stco, stss. +* avifImageCopy() no longer accepts source U and V channels to be NULL for + non-4:0:0 input if Y is not NULL and if AVIF_PLANES_YUV is specified. +* The default values of the maxQuantizer and maxQuantizerAlpha members of + avifEncoder changed from AVIF_QUANTIZER_LOSSLESS (0) to + AVIF_QUANTIZER_WORST_QUALITY (63). The behavior changed if minQuantizer and + maxQuantizer are left initialized to the default values. Code should be + updated to set the quality member. Similarly for the alpha quantizers and + qualityAlpha. +* avifImageRGBToYUV() and avifImageYUVToRGB() handle avifImage bit depths 8, 10, + 12 and now also 16. Files read by apps/shared/ can output 16-bit avifImage + instances. +* Update aom.cmd: v3.6.1 +* Update dav1d.cmd: 1.2.1 +* Update libsharpyuv: 0.4.0 +* Update rav1e.cmd: v0.6.6 +* Update svt.cmd/svt.sh: v1.6.0 +* Update zlibpng.cmd: zlib 1.2.13 and libpng 1.6.39 +* avifImageCreate(), avifImageCreateEmpty(), avifEncoderCreate() and other + internal functions now return NULL if a memory allocation failed. +* avifEncoderSetCodecSpecificOption() now returns avifResult instead of void to + report memory allocation failures. +* At decoding, avifIOStats now returns the same values as at encoding. +* avifRGBImageAllocatePixels(), avifRWDataRealloc(), avifRWDataSet(), + avifImageSetProfileICC(), avifImageSetMetadataExif() and + avifImageSetMetadataXMP() now return avifResult instead of void to report + memory allocation failures. +* avifReadImage(), avifJPEGRead() and avifPNGRead() now remove the trailing zero + byte from read XMP chunks, if any. See avifImageFixXMP(). +* Force keyframe for alpha if color is a keyframe. +* Write primaries and transfer characteritics info in decoded PNG. +* Add support for reading PNG gAMA, cHRM and sRGB chunks. +* The 'mode' member of the avifImageMirror struct was renamed 'axis'. +* Change the type of the 'depth' parameter from int to uint32_t in + avifFullToLimitedY(), avifFullToLimitedUV(), avifLimitedToFullY(), and + avifLimitedToFullUV(). + +## [0.11.1] - 2022-10-19 + +### Changed +* avifincrtest_helpers: Cast 64-bit offset to size_t +* avifmetadatatest: don't include avif/internal.h +* avifrgbtoyuvtest: skip if no libsharpyuv +* Disable tests that may fail if the codec is not aom (#1176) + +## [0.11.0] - 2022-10-12 + +There are incompatible ABI changes in this release. The alphaRange member was +removed from the avifImage struct. The chromaDownsampling and avoidLibYUV +members were added to the avifRGBImage struct. The imageDimensionLimit member +was added to the avifDecoder struct. avifImageCopy() and +avifImageAllocatePlanes() signatures changed. It is necessary to recompile your +code. Also check the return values of avifImageCopy() and +avifImageAllocatePlanes(). + +### Added +* Add man pages for avifenc and avifdec +* Add the avifChannelIndex type alias for enum avifChannelIndex +* Add avifChromaDownsampling enum +* Add chromaDownsampling field to avifRGBImage struct +* Add support for AVIF_RGB_FORMAT_RGB_565 +* Add imageDimensionLimit field to avifDecoder struct +* Add autoTiling field to avifEncoder struct +* Add new avifResult codes AVIF_RESULT_CANNOT_CHANGE_SETTING and + AVIF_RESULT_INCOMPATIBLE_IMAGE +* Add new enum constants AVIF_PIXEL_FORMAT_COUNT and AVIF_RGB_FORMAT_COUNT +* avifdec: Add --dimension-limit, which specifies the image dimension limit + (width or height) that should be tolerated +* avifenc: Add --sharpyuv, which enables "sharp" RGB to YUV420 conversion, which + reduces artifacts caused by 420 chroma downsampling. Needs libsharpyuv (part + of the libwebp repository) at compile time. +* avifenc: Add --ignore-exif and --ignore-xmp flags. +* avifenc: Add --autotiling, which sets --tilerowslog2 and --tilecolslog2 + automatically. +* avifenc: Input Exif orientation is converted to irot/imir by default. + +### Changed +* Fix memory leaks of metadata on avifenc exit +* Update the handling of 'lsel' and progressive decoding to AVIF spec v1.1.0 +* Treat an absent lsel and layer_id == 0xFFFF equivalently for backward + compatibility with earlier drafts of AVIF spec v1.1.0 +* Set libavif's own default value of cfg.rc_end_usage for libaom +* Fix https://github.com/AOMediaCodec/libavif/issues/953 +* Set the libaom-specific option -a tune=ssim by default +* Bump cmake_minimum_required from 3.5 to 3.13 +* Fix https://crbug.com/oss-fuzz/48135 +* Use several new libyuv functions in reformat_libyuv.c +* Fix SVT-AV1's issue 1957 related to uninitialized variables crashing the + encoder +* Fix https://github.com/AOMediaCodec/libavif/issues/787 +* Update aom.cmd: v3.5.0 +* Update rav1e.cmd: v0.5.1 +* Update svt.cmd/svt.sh: v1.2.1 +* Update libgav1.cmd: v0.18.0 +* Update libyuv.cmd: f9fda6e7 (version 1844) +* avifImageCopy() and avifImageAllocatePlanes() now return avifResult instead of + void to report invalid parameters or memory allocation failures. +* avifImageRGBToYUV() now uses libyuv fast paths by default. It may slightly + change conversion results. The old behavior can be restored by setting + avifRGBImage::chromaDownsampling to AVIF_CHROMA_DOWNSAMPLING_BEST_QUALITY + and avifRGBImage::avoidLibYUV to AVIF_TRUE. +* avifRGBImage::chromaUpsampling now only applies to conversions that need + upsampling chroma from 4:2:0 or 4:2:2 and has no impact on the use of libyuv. + Set avifRGBImage::avoidLibYUV accordingly to control the use of libyuv. +* avifenc: Set the YUV format to 4:0:0 for grayscale PNGs +* Support updating encoder settings and codec-specific options during encoding +* Disable AVIF_STRICT_CLAP_VALID and AVIF_STRICT_PIXI_REQUIRED in the JNI + wrapper +* avifdec: Return proper exit code in "info" mode +* In avifenc and avifdec, treat all arguments that start with '-' as options +* Fix https://github.com/AOMediaCodec/libavif/issues/1086 +* Exif and XMP metadata is imported from PNG and JPEG files. +* avifImageSetMetadataExif() parses the Exif metadata and converts any Exif + orientation found into transformFlags, irot and imir values. +* Write 'auxi' box for animated images with alpha channel +* Write 'auxv' as handler_type for alpha channel track +* Use PNG_COLOR_TYPE_GRAY for 8-bit grayscale output +* Replace repeated subtraction by modulo in calcGCD (fix b/246649620) +* Change avifImageCreate to take uint32_t instead of int parameters +* When writing an image sequence, check if it's safe to cast width and height to + uint16_t +* Allow clamped grid cells in avifEncoderAddImageGrid() + +### Removed +* alphaRange field was removed from the avifImage struct. It it presumed that + alpha plane is always full range. +* The avifCodecConfigurationBox struct becomes a private type for libavif + internal use + +## [0.10.1] - 2022-04-11 + +### Changed +* tests/docker/build.sh: Build SVT-AV1 using cmake and ninja directly +* Fix a Visual Studio 2017 compiler warning in src\reformat.c: warning C4204: + nonstandard extension used: non-constant aggregate initializer +* Fix the help message of avifdec: --index takes a value + +## [0.10.0] - 2022-04-06 + +There is an incompatible ABI change in this release. New members were added to +the avifDecoder and avifRGBImage structs. It is necessary to recompile your +code. + +### Added +* Support F16 Half Float conversion in avifRGBImage: new isFloat member +* Incremental decoding of AVIF grid tiles: new allowIncremental member in + avifDecoder and new avifDecoderDecodedRowCount() function +* Support parsing of version 3 of ItemInfoEntry +* Add new avifResult code AVIF_RESULT_OUT_OF_MEMORY +* Document the "[Strict]" prefix in error strings +* Document that SVT-AV1 doesn't support lossless yet +* CI: Add CIFuzz integration +* Add Docker build CI pipeline +* Add SVT-AV1 to CI and build scripts +* ci.yml: Build examples and apps + +### Changed +* Print the item type in the diagnostic messages for missing mandatory av1C or + pixi property +* Update aom.cmd: v3.3.0 +* Update dav1d.cmd: 1.0.0 +* Update libgav1.cmd: 0.17.0 +* Update rav1e.cmd: 0.5.0 +* Update svt.cmd/svt.sh: v0.9.1 +* Update zlibpng.cmd: zlib v1.2.12 +* findrav1e: add LDFLAGS to LIBRARIES +* rav1e: add bcrypt.lib to list of extra libs +* Fix y4m read/write for images of non-standard dimensions +* Fix y4mRead() and y4mWrite() for 4:0:0 +* Fix compilation with Clang 13 and 14 +* Remove the obsolete script fuzz.sh +* Support local android builds for libgav1 +* Add Android JNI bindings +* Delay failures of AV1 codecs not existing to frame decoding, to allow libavif + to perform AVIF parsing without any AV1 codecs +* Change encoder speed in gdk-pixbuf plug-in +* Fix compilation with 1755 <= LIBYUV_VERSION < 1774 +* Remove JSON-based tests (as they are unreliable), along with associated + helper code (cJSON, compare) +* CMakeLists.txt: Move codec enabled message after check passed +* Fix alpha copy in aomCodecEncodeImage() +* Support SVT-AV1 v0.9.0 or later +* Call svt_av1_get_version() for SVT-AV1 v0.9.0 or later +* Handle avifArrayCreate() failures +* Only consider a frame index to be a keyframe if all tiles/planes are sync + frames +* Move checks to avifAreGridDimensionsValid() +* avifArrayPop() should zero the popped element +* avifDecoderReset() should not return AVIF_FALSE +* Handle avifDecoderDataCreateTile() failures +* Fix endian dependent parameters to avifRWStreamWrite +* Mark the input images of an image grid as hidden +* Write ccst box in Sample Entry for animated images +* Add iso8 to compatible_brands for animated images +* Compare with snapshot of AOM_EXT_PART_ABI_VERSION +* Handle the new AOM_IMG_FMT_NV12 enum conditionally in a switch statement in + aomCodecGetNextImage() +* Fix avifpng.c for libpng 1.4 +* Fix -Wformat / -Wformat-non-iso on MinGW UCRT +* Replace some memcpy calls with struct assignments +* Remove unnecessary memcpy() calls in src/utils.c +* Split CMakeLists.txt into tests/CMakeLists.txt +* Use bilinear chroma upsampling in libyuv when possible +* Call libyuv functions to convert 10bpc YUV to 8bpc RGB +* Prepare avif example for non-aborting avifAlloc() +* Handle the tileRowsLog2 and tileColsLog2 members of avifEncoder correctly for + SVT-AV1. + +## [0.9.3] - 2021-10-20 + +### Added +* Support for progressive AVIFs and operating point selection +* Add automatic tile scaling to the item's ispe or track's dims +* Add diagnostic messages for AV1 decode failures +* avifdec: Add PNG compression level arg +* Make image size limit configurable, expose to avifdec +* Add the AVIF_STRICT_ALPHA_ISPE_REQUIRED flag + +### Changed +* Mandate ispe and disallow zero width or height (#640). +* Re-map libavif speed 7-10 to libaom speed 7-9 (#682) +* Refer to https://aomedia-review.googlesource.com/c/aom/+/140624 +* If you were using libaom with the following avif speed setting: +* - speed 0-6: no change is needed +* - speed 7: change to speed 6 for the same results +* - speed 8-9: re-test and re-adjust speed according to your app needs +* Update aom.cmd: v3.2.0 +* Update dav1d.cmd: 0.9.2 +* Update svt-av1.cmd: v0.9.0 +* Pass TestCase's minQuantizer, maxQuantizer, speed to encoder. +* Regenerate tests.json +* Disable JSON-based tests for now, the metrics are inconsistent/unreliable +* Set diagnostic message for aom_codec_set_option() +* Re-map libavif-libaom speed settings (#682) +* Bump of version in CMakeLists.txt was forgotten +* avifdec: Better message for unsupported file extension +* Do not copy input image when encoding with libaom unless width or height is 1 +* Fix the comment for AVIF_STRICT_PIXI_REQUIRED +* Update libavif.pc.cmake (#692) +* In 32-bit builds set dav1d's frame_size_limit setting to 8192*8192 +* Allocate alpha alongside YUV (if necessary) during y4m decode to avoid incorrect alphaRowBytes math +* Change avif_decode_fuzzer to be more like Chrome +* Update codec_dav1d.c for the new threading model +* Generalized ipco property deduplication +* Rename avifParseMoovBox to avifParseMovieBox for consistency +* Simplify idat storage for avifMeta structure (#756) +* Fix oss-fuzz coverage build failure of dav1d +* Redesign AVIF_DECODER_SOURCE_AUTO to honor the FileTypeBox's major brand +* Use "C420" as default Y4M color space parameter + +## [0.9.2] - 2021-06-23 + +### Added +* avifenc, avifdec: Allow "-j all" to automatically use all of the cores on the machine (#670) + +### Changed +* Refactor imir implementation to match HEIF Draft Amendment 2 (#665) +* Merge avifCodec's open call with its getNextImage call to avoid codec init during parse, and simplify the codec API (#637) +* Update aom.cmd: v3.1.1 (#674) +* Update svt-av1: v0.8.7 (#627) +* Make tests/compare.h and tests/testcase.h C++ safe (#678) +* Print width and height as %ux%u instead of %u/%u (#676) +* Allocate codec->internal->svt_config statically (#675) +* Cleanup related to avifDiagnosticsClearError() (#673) +* Cleanup avifutil.h comment to match libavif style (#671) +* Fix the clang -Wunused-macros warning (#672) +* Check for int32_t overflows in 'clap' code (#663) +* Have avifdec print chroma sample position for 420 (#666) +* Enable CMake configs in VCPKG mode (#659) +* Avoid multiplying widthN and heightN by 2 (#662) +* Correct AVIF_PIXEL_FORMAT_NONE handling logic (#654) +* Cast extent->offset (a uint64_t) to size_t safely (#660) +* Disallow negative clap width or height (#656) +* Check for int32_t cast and unsigned add overflows (#655) +* Some straightforward changes to clapFraction code (#653) +* Fix box name of avifParseChunkOffsetBox (#652) +* No need to pass diag to functions that have 'data' (#651) +* Simplify the assertion in avifROStreamStart() (#650) +* Don't clear error in avifEncoderSetCodecSpecificOp (#648) +* Simplify avifCodecConfigurationBoxGetFormat (#646) +* Print the fraction in "not an integer" messages (#641) +* Fix a typo in the diagnostic context for 'ipco' (#644) +* Remove const from non-pointer function parameters (#634) +* Declare the param of avifDumpDiagnostics as const (#633) +* Adjust gdk-pixbuf loader for new API change (#668) +* Fix gdk-pixbuf loader install path (#615) + +## [0.9.1] - 2021-05-19 + +### Added +* Added strict mode/flags (enabled by default): `AVIF_STRICT_PIXI_REQUIRED`, `AVIF_STRICT_CLAP_VALID` +* avifdec: Added `--no-strict` to disable all strict flags +* avifdec: Added `-r` (`--raw-color`), which avoids multiplying against AVIF alpha channel before packing into non-alpha formats (JPEG) +* avifenc: Recognize the Y4M format string "C420mpeg2" +* avifenc: Add `--crop` convenient alternative arg to the difficult-to-use `--clap` arg +* avifenc: New default for `--yuv`: `"auto"`, which will use a source JPEG's internal YUV format instead of YUV444, if detected + * Uses: Prevent colorspace conversion when reading from JPEG if possible (tongyuantongyu) +* avifenc/avifdec: Add helpful values/calculations when dumping clap box +* Added avifDiagnostics, which allows for a detailed, freeform error string upon decode or encode error +* Create helper avifCropRect struct and methods for helping to manipulate/populate/validate avifCleanApertureBox +* Added ability to set codec-specific options for color or alpha only +* Support for libaom's ALL_INTRA mode (if available) +* Create avifDecoder.imageCountLimit as a sanity check against malformed files +* SVT: Image sequence encoding support (tongyuantongyu) +* Added rav1e to AppVeyor builds + +### Changed +* avifenc/avifdec: Link AOM_LIBRARIES and use CXX if vmaf is present (1480c1) +* Ensure that an AVIF has a ftyp box, and based on ftyp, has other appropriate toplevel boxes present as well +* Avoid linking against libyuv if it is too old / incompatible +* Always require a primary item when decoding items +* Add some strictness around ipma box parsing (version/flags tuples must be unique across ipma boxes in a file) +* Fix alpha grids by properly writing alpha grid metadata payload +* A HandlerBox (hdlr) of type 'pict' must be the first box within the MetaBox (meta) +* Add some typedefs for various flag decls in avif.h to self-document which flags should be used in which function arguments +* When encoding single-frame images using libaom, clean up the encoder immediately after encoding the frame to cut down on resources high watermarks +* Fail on reformat Identity (MC=0) with subsampling (not using YUV444) +* Warn if alpha is limited range (deprecated) +* Validate the first_chunk fields in the stsc box +* In libaom all intra mode, set cq-level for user +* Check the return values of some aom_codec_ calls and add diagnostics output (wantehchang) +* Use aom_codec_set_option() if available (allows for future compat with libaom 3.0+ advanced features) +* rav1e: Use cargo cinstall in local builds to ensure consistency in target output, as cbuild no longer builds directly into target/release +* Tweaks to compiler flags (analyze related) +* Use libyuv BT.709 & 2020 full range YuvConstants (wantehchang) +* Multiply color with alpha for opaque RGB format during conversion (see #520) +* Switch docker to ubuntu 20.04, fix tzdata install (paskal) +* Added an "Understanding maxThreads" explanatory comment block in avif.h +* Minor fixes to support AVIF_CODEC_AOM_ENCODE +* Various minor code/comments cleanup +* CI tweaks, macOS build, and caching / speed increases (EwoutH) +* Update aom.cmd: v3.1.0 +* Update dav1d.cmd: 0.9.0 +* Update libgav1: v0.16.3 +* Update libyuv.cmd: 2f0cbb9 + ## [0.9.0] - 2021-02-22 ### Added @@ -506,7 +1065,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added decoder and image timings for image sequences ### Changed -- Reorganized internal struct avifCodec to accomodate multiple codecs simultaneously (compile time; not exposed to API) +- Reorganized internal struct avifCodec to accommodate multiple codecs simultaneously (compile time; not exposed to API) - Fix some compiler warnings - Sanity check offsets and sizes in items table before using - Bail out of box header advertises an impossible size @@ -575,7 +1134,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Constants `AVIF_VERSION`, `AVIF_VERSION_MAJOR`, `AVIF_VERSION_MINOR`, `AVIF_VERSION_PATCH` - `avifVersion()` function -[Unreleased]: https://github.com/AOMediaCodec/libavif/compare/v0.9.0...HEAD +[Unreleased]: https://github.com/AOMediaCodec/libavif/compare/v1.1.1...HEAD +[1.1.1]: https://github.com/AOMediaCodec/libavif/compare/v1.1.0...v1.1.1 +[1.1.0]: https://github.com/AOMediaCodec/libavif/compare/v1.0.0...v1.1.0 +[1.0.4]: https://github.com/AOMediaCodec/libavif/compare/v1.0.3...v1.0.4 +[1.0.3]: https://github.com/AOMediaCodec/libavif/compare/v1.0.2...v1.0.3 +[1.0.2]: https://github.com/AOMediaCodec/libavif/compare/v1.0.1...v1.0.2 +[1.0.1]: https://github.com/AOMediaCodec/libavif/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/AOMediaCodec/libavif/compare/v0.11.1...v1.0.0 +[0.11.1]: https://github.com/AOMediaCodec/libavif/compare/v0.11.0...v0.11.1 +[0.11.0]: https://github.com/AOMediaCodec/libavif/compare/v0.10.1...v0.11.0 +[0.10.1]: https://github.com/AOMediaCodec/libavif/compare/v0.10.0...v0.10.1 +[0.10.0]: https://github.com/AOMediaCodec/libavif/compare/v0.9.3...v0.10.0 +[0.9.3]: https://github.com/AOMediaCodec/libavif/compare/v0.9.2...v0.9.3 +[0.9.2]: https://github.com/AOMediaCodec/libavif/compare/v0.9.1...v0.9.2 +[0.9.1]: https://github.com/AOMediaCodec/libavif/compare/v0.9.0...v0.9.1 [0.9.0]: https://github.com/AOMediaCodec/libavif/compare/v0.8.4...v0.9.0 [0.8.4]: https://github.com/AOMediaCodec/libavif/compare/v0.8.3...v0.8.4 [0.8.3]: https://github.com/AOMediaCodec/libavif/compare/v0.8.2...v0.8.3 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cc54ef..9f7cd1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,37 @@ # Copyright 2019 Joe Drago. All rights reserved. # SPDX-License-Identifier: BSD-2-Clause -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.13) -# Specify search path for CMake modules to be loaded by include() -# and find_package() +# New in CMake version 3.15. MSVC warning flags are not in CMAKE__FLAGS by default. +if(POLICY CMP0092) + cmake_policy(SET CMP0092 NEW) +endif() + +# Prevent warnings in CMake>=3.24 for ExternalProject_Add() +# see https://cmake.org/cmake/help/latest/policy/CMP0135.html +if(POLICY CMP0135) + cmake_policy(SET CMP0135 NEW) # valid for DOWNLOAD_EXTRACT_TIMESTAMP option in CMake 3.24 and later +endif() + +# New in CMake version 3.30. FetchContent_Populate() is deprecated, call +# FetchContent_MakeAvailable() instead. +if(POLICY CMP0169) + cmake_policy(SET CMP0169 OLD) +endif() + +project(libavif LANGUAGES C VERSION 1.1.1) + +# The root directory of the avif source +set(AVIF_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + +# Specify search path for CMake modules to be loaded by include() and find_package() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") -project(libavif LANGUAGES C VERSION 0.9.0) +include(ExternalProject) +include(FetchContent) +include(FindPkgConfig) +include(AvifExternalProjectUtils) # Set C99 as the default set(CMAKE_C_STANDARD 99) @@ -19,36 +43,111 @@ set(CMAKE_C_STANDARD 99) # Increment MINOR. Set PATCH to 0 # If the source code was changed, but there were no interface changes: # Increment PATCH. -set(LIBRARY_VERSION_MAJOR 10) -set(LIBRARY_VERSION_MINOR 0) -set(LIBRARY_VERSION_PATCH 0) +set(LIBRARY_VERSION_MAJOR 16) +set(LIBRARY_VERSION_MINOR 1) +set(LIBRARY_VERSION_PATCH 1) set(LIBRARY_VERSION "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}") set(LIBRARY_SOVERSION ${LIBRARY_VERSION_MAJOR}) option(BUILD_SHARED_LIBS "Build shared avif library" ON) set(CMAKE_STATIC_LIBRARY_SUFFIX "_a.lib") -option(AVIF_ENABLE_WERROR "Treat all compiler warnings as errors" ON) +option(AVIF_ENABLE_WERROR "Treat all compiler warnings as errors" OFF) +option(AVIF_ENABLE_NODISCARD "Add [[nodiscard]] to some functions. CMake must be at least 3.21 to force C23" OFF) -option(AVIF_CODEC_AOM "Use the AOM codec for encoding/decoding (see AVIF_CODEC_AOM_DECODE/AVIF_CODEC_AOM_ENCODE)" OFF) -option(AVIF_CODEC_DAV1D "Use the dav1d codec for decoding" OFF) -option(AVIF_CODEC_LIBGAV1 "Use the libgav1 codec for decoding" OFF) -option(AVIF_CODEC_RAV1E "Use the rav1e codec for encoding" OFF) -option(AVIF_CODEC_SVT "Use the SVT-AV1 codec for encoding" OFF) +option(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R "Enable experimental YCgCo-R matrix code" OFF) +option(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP + "Enable experimental gain map code (for HDR images that look good both on HDR and SDR displays)" OFF +) +option(AVIF_ENABLE_EXPERIMENTAL_METAV1 "Enable experimental reduced header" OFF) +option(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM "Enable experimental sample transform code" OFF) + +set(AVIF_PKG_CONFIG_EXTRA_LIBS_PRIVATE "") +set(AVIF_PKG_CONFIG_EXTRA_REQUIRES_PRIVATE "") + +function(set_local_or_system_option VAR DEFAULT TEXT) + # Deal with the older way of setting options. + if(DEFINED AVIF_LOCAL_${VAR}) + if(AVIF_LOCAL_${VAR}) + set(DEFAULT "LOCAL") + else() + set(DEFAULT "SYSTEM") + endif() + message(WARNING "Setting AVIF_LOCAL_${VAR} is deprecated. " "Set AVIF_${VAR} to ${DEFAULT} instead.") + elseif(DEFINED AVIF_${VAR}) + set(DEFAULT ${AVIF_${VAR}}) + endif() + set(AVIF_${VAR} ${DEFAULT} CACHE STRING ${TEXT} FORCE) + set_property(CACHE AVIF_${VAR} PROPERTY STRINGS OFF LOCAL SYSTEM) +endfunction() +function(set_codec_option CODEC NAME ENCDEC EXTRA) + if(DEFINED AVIF_CODEC_${CODEC}) + set(DEFAULT ${AVIF_CODEC_${CODEC}}) + # Deal with the older way of setting options. + if(AVIF_CODEC_${CODEC} STREQUAL "ON") + if(AVIF_LOCAL_${CODEC}) + set(DEFAULT "LOCAL") + else() + set(DEFAULT "SYSTEM") + endif() + message(WARNING "Setting AVIF_CODEC_${CODEC} and AVIF_LOCAL_${CODEC} is deprecated. " + "Set AVIF_CODEC_${CODEC} to ${DEFAULT} instead." + ) + endif() + else() + set(DEFAULT "OFF") + endif() + if(AVIF_CODEC_${CODEC} STREQUAL "OFF" AND AVIF_LOCAL_${CODEC} STREQUAL "OFF") + message(WARNING "Setting AVIF_LOCAL_${CODEC} is deprecated. " "Only set AVIF_CODEC_${CODEC} to OFF instead.") + endif() + set(AVIF_CODEC_${CODEC} ${DEFAULT} CACHE STRING "Use the ${NAME} codec for ${ENCDEC}${EXTRA}" FORCE) + set_property(CACHE AVIF_CODEC_${CODEC} PROPERTY STRINGS OFF LOCAL SYSTEM) +endfunction() +set_codec_option(AOM "AOM" "encoding/decoding" " (see AVIF_CODEC_AOM_DECODE/AVIF_CODEC_AOM_ENCODE)") +set_codec_option(DAV1D "dav1d" "decoding" "") +set_codec_option(LIBGAV1 "libgav1" "decoding" "") +set_codec_option(RAV1E "rav1e" "encoding" "") +set_codec_option(SVT "SVT-AV1" "encoding" "") +set_codec_option(AVM "AVM (AV2)" "encoding/decoding" " (EXPERIMENTAL)") # These options allow libavif to only link against / use libaom's encoder or decoder, instead of being forced to use both -option(AVIF_CODEC_AOM_DECODE "if AVIF_CODEC_AOM is on, use/offer libaom's decoder" ON) -option(AVIF_CODEC_AOM_ENCODE "if AVIF_CODEC_AOM is on, use/offer libaom's encoder" ON) +include(CMakeDependentOption) +cmake_dependent_option( + AVIF_CODEC_AOM_DECODE "if AVIF_CODEC_AOM is on, use/offer libaom's decoder" ON "NOT AVIF_CODEC_AOM STREQUAL OFF" OFF +) +cmake_dependent_option( + AVIF_CODEC_AOM_ENCODE "if AVIF_CODEC_AOM is on, use/offer libaom's encoder" ON "NOT AVIF_CODEC_AOM STREQUAL OFF" OFF +) -option(AVIF_LOCAL_AOM "Build the AOM codec by providing your own copy of the repo in ext/aom (see Local Builds in README)" OFF) -option(AVIF_LOCAL_DAV1D "Build the dav1d codec by providing your own copy of the repo in ext/dav1d (see Local Builds in README)" OFF) -option(AVIF_LOCAL_LIBGAV1 "Build the libgav1 codec by providing your own copy of the repo in ext/libgav1 (see Local Builds in README)" OFF) -option(AVIF_LOCAL_RAV1E "Build the rav1e codec by providing your own copy of the repo in ext/rav1e (see Local Builds in README)" OFF) -option(AVIF_LOCAL_SVT "Build the SVT-AV1 codec by providing your own copy of the repo in ext/SVT-AV1 (see Local Builds in README)" OFF) +set_local_or_system_option( + "GTEST" OFF + "Build the GoogleTest framework by providing your own copy of the repo in ext/googletest (see Local Builds in README)" +) +option(AVIF_BUILD_APPS "Build avif apps." OFF) +option(AVIF_BUILD_TESTS "Build avif tests." OFF) +option( + AVIF_ENABLE_COMPLIANCE_WARDEN + "Check all avifEncoderFinish() output for AVIF specification compliance. Depends on gpac/ComplianceWarden which can be added with ext/compliance_warden.sh" + OFF +) +option( + AVIF_ENABLE_GOLDEN_TESTS + "Build tests that compare encoding outputs to golden files. Needs AVIF_BUILD_APPS=ON and AVIF_BUILD_TESTS=ON, and depends on MP4box which can be built with ext/mp4box.sh" + OFF +) +option(AVIF_ENABLE_GTEST + "Build avif C++ tests, which depend on GoogleTest. Requires GoogleTest. Has no effect unless AVIF_BUILD_TESTS is ON." ON +) +option(AVIF_ENABLE_FUZZTEST "Build avif fuzztest targets. Requires Google FuzzTest. Has no effect unless AVIF_BUILD_TESTS is ON." + OFF +) +option(AVIF_LOCAL_FUZZTEST + "Build the Google FuzzTest framework by providing your own copy of the repo in ext/fuzztest (see Local Builds in README)" + OFF +) -if(AVIF_LOCAL_LIBGAV1) - enable_language(CXX) -endif() +# Whether the libavif library uses c++ indirectly (e.g. through linking to libyuv). +set(AVIF_LIB_USE_CXX OFF) if(APPLE) set(XCRUN xcrun) @@ -56,387 +155,500 @@ else() set(XCRUN) endif() -# --------------------------------------------------------------------------------------- -# This insanity is for people embedding libavif or making fully static or Windows builds. -# Any proper unix environment should ignore these entire following blocks. -option(AVIF_LOCAL_ZLIBPNG "Build zlib and libpng by providing your own copy inside the ext subdir." OFF) -if(AVIF_LOCAL_ZLIBPNG) - add_subdirectory(ext/zlib) - # Put the value of ZLIB_INCLUDE_DIR in the cache. This works around cmake behavior that has been updated by - # cmake policy CMP0102 in cmake 3.17. Remove the CACHE workaround when we require cmake 3.17 or later. See - # https://gitlab.kitware.com/cmake/cmake/-/issues/21343. - set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/zlib" CACHE PATH "zlib include dir") - include_directories("${CMAKE_CURRENT_BINARY_DIR}/ext/zlib") - set(CMAKE_DEBUG_POSTFIX "") - - # This is the only way I could avoid libpng going crazy if it found awk.exe, seems benign otherwise - set(PREV_ANDROID ${ANDROID}) - set(ANDROID TRUE) - set(PNG_BUILD_ZLIB "${CMAKE_CURRENT_SOURCE_DIR}/ext/zlib" CACHE STRING "" FORCE) - set(PNG_SHARED OFF CACHE BOOL "") - set(PNG_TESTS OFF CACHE BOOL "") - add_subdirectory(ext/libpng) - set(PNG_PNG_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libpng") - set(PNG_LIBRARY png_static) - include_directories("${CMAKE_CURRENT_BINARY_DIR}/ext/libpng") - set(ANDROID ${PREV_ANDROID}) - - set(ZLIB_LIBRARY zlibstatic) -endif() -option(AVIF_LOCAL_JPEG "Build jpeg by providing your own copy inside the ext subdir." OFF) -if(AVIF_LOCAL_JPEG) - add_subdirectory(ext/libjpeg) - if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") - set(JPEG_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libjpeg") - set(JPEG_LIBRARY jpeg) - else() - set(JPEG_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libjpeg" PARENT_SCOPE) - set(JPEG_LIBRARY jpeg PARENT_SCOPE) - endif() +# This is also needed to get shared libraries (e.g. pixbufloader-avif) to compile against a static libavif. +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +if(BUILD_SHARED_LIBS) + set(AVIF_LIBRARY_PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}") +else() + set(AVIF_LIBRARY_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}") endif() -option(AVIF_LOCAL_LIBYUV "Build libyuv by providing your own copy inside the ext subdir." OFF) -if(AVIF_LOCAL_LIBYUV) - set(LIB_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/ext/libyuv/build/${CMAKE_STATIC_LIBRARY_PREFIX}yuv${CMAKE_STATIC_LIBRARY_SUFFIX}") - if(NOT EXISTS "${LIB_FILENAME}") - message(FATAL_ERROR "libavif(AVIF_LOCAL_LIBYUV): ${LIB_FILENAME} is missing, bailing out") + +add_library(avif_obj OBJECT) +add_library(avif) + +# Adds to avif_obj's public link libraries for build, and adds +# the library as an install link library for export in case a consumer +# needs to include that library alongside libavif when statically linking. +function(avif_target_link_library target) + target_link_libraries(avif_obj PUBLIC $) + get_target_property(target_is_local ${target} AVIF_LOCAL) + if(target_is_local) + return() endif() - if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") - set(LIBYUV_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libyuv/include") - set(LIBYUV_LIBRARY ${LIB_FILENAME}) + get_target_property(install_target ${target} IMPORTED_SONAME) + if(NOT install_target) + set(install_target ${target}) + endif() + # The transitive dependency needs to be an export link library in a static build. + if(NOT BUILD_SHARED_LIBS) + target_link_libraries(avif PUBLIC $) + endif() +endfunction() + +#[[ +check_avif_option(