├── .github ├── dependabot.yml └── workflows │ ├── build-debian-packages.yml │ ├── build-on-Windows.yml │ ├── build-on-linux.yml │ └── build-on-macOS.yml ├── .gitignore ├── .gitmodules ├── .idea ├── davif.iml ├── misc.xml └── modules.xml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── debian ├── .gitignore ├── README.Debian ├── README.source ├── changelog ├── compat ├── control ├── copyright ├── davif-docs.docs ├── davif.cron.d.ex ├── davif.doc-base.EX ├── manpage.1.ex ├── manpage.sgml.ex ├── manpage.xml.ex ├── menu.ex ├── rules ├── source │ └── format └── watch.ex ├── doc └── ja_JP │ ├── README.md │ └── usage.md ├── patches └── zlib.patch ├── scripts ├── apply-patches.sh ├── build-debian-package.sh ├── build-deps.sh ├── reset-submodules.sh └── test.sh └── src ├── img ├── Conversion.cpp ├── Conversion.hpp └── png │ ├── Writer.cpp │ └── Writer.hpp └── main.cpp /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gitsubmodule" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | time: "02:00" 8 | timezone: "Asia/Tokyo" 9 | reviewers: 10 | - "ledyba-z" 11 | - package-ecosystem: "github-actions" 12 | directory: "/" 13 | schedule: 14 | interval: "weekly" 15 | time: "02:00" 16 | timezone: Asia/Tokyo 17 | reviewers: 18 | - "ledyba-z" 19 | -------------------------------------------------------------------------------- /.github/workflows/build-debian-packages.yml: -------------------------------------------------------------------------------- 1 | name: Build debian packages 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - dependabot/** 7 | tags: 8 | - v* 9 | pull_request: 10 | branches: 11 | - master 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | codename: [bionic, focal] 19 | steps: 20 | - uses: actions/checkout@v3 21 | with: 22 | submodules: 'recursive' 23 | fetch-depth: 0 24 | - name: Build debian package 25 | uses: link-u/execute-on-separated-ubuntu@master 26 | with: 27 | script: scripts/build-debian-package.sh 28 | on: ${{ matrix.codename }} 29 | - name: Upload result 30 | uses: actions/upload-artifact@v3 31 | with: 32 | name: ${{ matrix.codename }} 33 | path: | 34 | **/*.ddeb 35 | **/*.deb 36 | - name: Inspect disk usage 37 | shell: bash 38 | run: du -sh . 39 | 40 | test: 41 | needs: build 42 | runs-on: ubuntu-latest 43 | strategy: 44 | matrix: 45 | codename: [bionic, focal] 46 | steps: 47 | - uses: actions/checkout@v3 48 | - name: Download artifact 49 | uses: actions/download-artifact@v3 50 | with: 51 | name: ${{ matrix.codename }} 52 | path: artifact 53 | - name: Check debian package 54 | uses: link-u/execute-on-separated-ubuntu@master 55 | with: 56 | script: scripts/test.sh 57 | on: ${{ matrix.codename }} 58 | 59 | release: 60 | if: startsWith(github.ref, 'refs/tags/v') 61 | needs: test 62 | runs-on: ubuntu-latest 63 | steps: 64 | - name: Create release 65 | id: create_release 66 | uses: actions/create-release@v1.1.4 67 | env: 68 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 69 | with: 70 | tag_name: ${{ github.ref }} 71 | release_name: Release ${{ github.ref }} 72 | commitish: ${{ github.sha }} 73 | draft: true 74 | prerelease: true 75 | outputs: 76 | upload_url: ${{ steps.create_release.outputs.upload_url }} 77 | 78 | upload: 79 | needs: release 80 | runs-on: ubuntu-latest 81 | strategy: 82 | matrix: 83 | codename: [bionic, focal] 84 | steps: 85 | - name: Download artifact 86 | uses: actions/download-artifact@v3 87 | with: 88 | name: ${{ matrix.codename }} 89 | path: ${{ matrix.codename }} 90 | - name: Create a zip 91 | shell: bash 92 | run: zip ${{ matrix.codename }}.zip ${{ matrix.codename }}/* 93 | - name: Upload release asset 94 | uses: actions/upload-release-asset@v1.0.2 95 | env: 96 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 97 | with: 98 | upload_url: ${{ needs.release.outputs.upload_url }} 99 | asset_path: ${{ matrix.codename }}.zip 100 | asset_name: ${{ matrix.codename }}.zip 101 | asset_content_type: application/zip 102 | 103 | deploy: 104 | needs: upload 105 | runs-on: ubuntu-latest 106 | strategy: 107 | matrix: 108 | codename: [bionic, focal] 109 | steps: 110 | - name: Download artifact 111 | uses: actions/download-artifact@v3 112 | with: 113 | name: ${{ matrix.codename }} 114 | path: ${{ matrix.codename }} 115 | - name: Listup files 116 | shell: bash 117 | run: find . 118 | - name: Deploy 119 | shell: bash 120 | run: | 121 | printenv DEPLOY_SCRIPT | base64 -d > deploy.sh 122 | bash deploy.sh upload "${{ matrix.codename }}" "avif" "${{ matrix.codename }}" 123 | env: 124 | DEPLOY_SCRIPT: ${{ secrets.YOROZU_DEPLOY_SCRIPT }} 125 | 126 | sign: 127 | needs: deploy 128 | runs-on: ubuntu-latest 129 | steps: 130 | - name: Sign 131 | shell: bash 132 | run: | 133 | printenv DEPLOY_SCRIPT | base64 -d > deploy.sh 134 | bash deploy.sh sign 135 | env: 136 | DEPLOY_SCRIPT: ${{ secrets.YOROZU_DEPLOY_SCRIPT }} 137 | -------------------------------------------------------------------------------- /.github/workflows/build-on-Windows.yml: -------------------------------------------------------------------------------- 1 | name: Build on Windows 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - dependabot/** 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | runs-on: windows-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | submodules: 'recursive' 18 | fetch-depth: 0 19 | - uses: msys2/setup-msys2@v2 20 | with: 21 | msystem: MINGW64 22 | path-type: strict 23 | - name: Install dependencies 24 | shell: msys2 {0} 25 | run: | 26 | set +eux 27 | export HOME=${{ github.workspace }} 28 | pacman -S --noconfirm \ 29 | git \ 30 | patch \ 31 | \ 32 | base-devel \ 33 | mingw-w64-x86_64-toolchain \ 34 | \ 35 | mingw-w64-x86_64-cmake \ 36 | mingw-w64-x86_64-nasm \ 37 | mingw-w64-x86_64-yasm \ 38 | mingw-w64-x86_64-meson \ 39 | mingw-w64-x86_64-ninja \ 40 | \ 41 | mingw-w64-x86_64-dlfcn 42 | - name: build dependencies 43 | shell: msys2 {0} 44 | run: | 45 | set +eux 46 | export HOME=${{ github.workspace }} 47 | bash scripts/reset-submodules.sh 48 | bash scripts/apply-patches.sh 49 | bash scripts/build-deps.sh 50 | - name: configure 51 | shell: msys2 {0} 52 | run: | 53 | set +eux 54 | export HOME=${{ github.workspace }} 55 | cmake -S . -B build -G Ninja '-DCMAKE_CXX_FLAGS=-static' 56 | - name: make 57 | shell: msys2 {0} 58 | run: | 59 | set +eux 60 | export HOME=${{ github.workspace }} 61 | cd build 62 | ninja -v 63 | strip davif.exe 64 | - name: Upload result 65 | uses: actions/upload-artifact@v3 66 | with: 67 | name: davif-win64 68 | path: build/davif.exe 69 | -------------------------------------------------------------------------------- /.github/workflows/build-on-linux.yml: -------------------------------------------------------------------------------- 1 | name: Build on Linux 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - dependabot/** 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | os: [ubuntu-18.04, ubuntu-20.04] 17 | steps: 18 | - uses: actions/checkout@v3 19 | with: 20 | submodules: 'recursive' 21 | fetch-depth: 0 22 | - name: Install dependencies 23 | shell: bash 24 | run: | 25 | # Workaround: gcc >= 8.0 is required. 26 | case $(lsb_release -cs) in 27 | bionic) 28 | sudo apt install -y --no-install-recommends \ 29 | gcc-8 g++-8 yasm nasm python3-venv python3-pip python3-setuptools pkg-config ;; 30 | *) 31 | sudo apt install -y --no-install-recommends \ 32 | gcc g++ yasm nasm python3-venv python3-pip python3-setuptools pkg-config ;; 33 | esac 34 | python3 -m venv venv 35 | source venv/bin/activate 36 | pip3 install wheel 37 | pip3 install meson 38 | pip3 install ninja 39 | - name: configure 40 | shell: bash 41 | run: | 42 | source venv/bin/activate 43 | # Workaround: gcc >= 8.0 is required. 44 | case $(lsb_release -cs) in 45 | bionic) 46 | export CC=gcc-8 47 | export CXX=g++-8 48 | # bionic's nasm is too old. 49 | sed -i -e 's/-Denable_asm=true/-Denable_asm=false/g' scripts/build-deps.sh 50 | ;; 51 | *) ;; 52 | esac 53 | bash scripts/reset-submodules.sh 54 | bash scripts/apply-patches.sh 55 | bash scripts/build-deps.sh 56 | cmake -S . -B build 57 | - name: make 58 | shell: bash 59 | run: | 60 | source venv/bin/activate 61 | env --chdir build make 62 | -------------------------------------------------------------------------------- /.github/workflows/build-on-macOS.yml: -------------------------------------------------------------------------------- 1 | name: Build on macOS 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - dependabot/** 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | runs-on: macos-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | submodules: 'recursive' 18 | fetch-depth: 0 19 | - name: Install dependencies 20 | shell: bash 21 | run: | 22 | python3 -m venv venv 23 | source venv/bin/activate 24 | pip3 install wheel 25 | pip3 install meson 26 | pip3 install ninja 27 | brew install yasm nasm 28 | - name: configure 29 | shell: bash 30 | run: | 31 | export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)" 32 | source venv/bin/activate 33 | bash scripts/reset-submodules.sh 34 | bash scripts/apply-patches.sh 35 | bash scripts/build-deps.sh 36 | cmake -S . -B build 37 | - name: make 38 | shell: bash 39 | run: | 40 | export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)" 41 | source venv/bin/activate 42 | (cd build && make) 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### 2 | *.bmp 3 | *.png 4 | *.avif 5 | /perf.data 6 | /perf.data.old 7 | /build/ 8 | /*.deb 9 | /*.ddeb 10 | 11 | ### C++ template 12 | # Compiled Object files 13 | *.slo 14 | *.lo 15 | *.o 16 | *.obj 17 | 18 | # Precompiled Headers 19 | *.gch 20 | *.pch 21 | 22 | # Compiled Dynamic libraries 23 | *.so 24 | *.dylib 25 | *.dll 26 | 27 | # Fortran module files 28 | *.mod 29 | 30 | # Compiled Static libraries 31 | *.lai 32 | *.la 33 | *.a 34 | *.lib 35 | 36 | # Executables 37 | *.exe 38 | *.out 39 | *.app 40 | 41 | # 42 | /build/ 43 | /cmake-build-*/ 44 | 45 | ### JetBrains template 46 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 47 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 48 | 49 | # User-specific stuff: 50 | .idea/workspace.xml 51 | .idea/tasks.xml 52 | .idea/dictionaries 53 | .idea/vcs.xml 54 | .idea/jsLibraryMappings.xml 55 | 56 | # Sensitive or high-churn files: 57 | .idea/dataSources.ids 58 | .idea/dataSources.xml 59 | .idea/dataSources.local.xml 60 | .idea/sqlDataSources.xml 61 | .idea/dynamic.xml 62 | .idea/uiDesigner.xml 63 | 64 | # Gradle: 65 | .idea/gradle.xml 66 | .idea/libraries 67 | 68 | # Mongo Explorer plugin: 69 | .idea/mongoSettings.xml 70 | 71 | ## File-based project format: 72 | *.iws 73 | 74 | ## Plugin-specific files: 75 | 76 | # IntelliJ 77 | /out/ 78 | 79 | # mpeltonen/sbt-idea plugin 80 | .idea_modules/ 81 | 82 | # JIRA plugin 83 | atlassian-ide-plugin.xml 84 | 85 | # Crashlytics plugin (for Android Studio and IntelliJ) 86 | com_crashlytics_export_strings.xml 87 | crashlytics.properties 88 | crashlytics-build.properties 89 | fabric.properties 90 | 91 | # 92 | /_deps/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/dav1d"] 2 | path = external/dav1d 3 | url = https://code.videolan.org/videolan/dav1d.git 4 | [submodule "external/libavif-container"] 5 | path = external/libavif-container 6 | url = https://github.com/link-u/libavif-container.git 7 | [submodule "external/libpng"] 8 | path = external/libpng 9 | url = https://git.code.sf.net/p/libpng/code 10 | [submodule "external/zlib"] 11 | path = external/zlib 12 | url = https://github.com/madler/zlib.git 13 | ignore = dirty 14 | [submodule "external/clipp"] 15 | path = external/clipp 16 | url = https://github.com/muellan/clipp.git 17 | -------------------------------------------------------------------------------- /.idea/davif.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(davif) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(ENABLE_DOCS OFF) 7 | 8 | if (WIN32) 9 | # https://stackoverflow.com/questions/47690822/possible-to-force-cmake-msvc-to-use-utf-8-encoding-for-source-files-without-a-bo 10 | add_compile_options("$<$:/utf-8>") 11 | add_compile_options("$<$:/utf-8>") 12 | 13 | # https://stackoverflow.com/a/60410369 14 | set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/_deps/lib/pkgconfig\;$ENV{PKG_CONFIG_PATH}") 15 | else(WIN32) 16 | set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/_deps/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") 17 | endif(WIN32) 18 | 19 | ############################################################################### 20 | add_subdirectory(external/libavif-container EXCLUDE_FROM_ALL) 21 | ############################################################################### 22 | # zlib 23 | set(ASM686L OFF CACHE BOOL "Enable building i686 assembly implementation" FORCE) 24 | set(ASM686 OFF CACHE BOOL "Enable building amd64 assembly implementation" FORCE) 25 | add_subdirectory(external/zlib EXCLUDE_FROM_ALL) 26 | set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/zlib" "${CMAKE_CURRENT_BINARY_DIR}/external/zlib") 27 | set(ZLIB_ROOT "${CMAKE_BINARY_DIR}/zlib") 28 | set(ZLIB_DIR "${CMAKE_BINARY_DIR}/zlib") 29 | ############################################################################### 30 | set(SKIP_INSTALL_ALL ON) 31 | 32 | set(PNG_BUILD_ZLIB ON CACHE BOOL "Custom zlib Location, else find_package is used" FORCE) 33 | set(PNG_SHARED OFF CACHE BOOL "Build shared lib" FORCE) 34 | set(PNG_STATIC ON CACHE BOOL "Build static lib" FORCE) 35 | set(PNG_TESTS OFF CACHE BOOL "Build libpng tests" FORCE) 36 | add_subdirectory(external/libpng EXCLUDE_FROM_ALL) 37 | #FIXME(ledyba-z): Workaround to include "pnglibconf.h" 38 | target_include_directories(png_static PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/external/libpng") 39 | # zlib 40 | target_link_directories(png_static PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/external/zlib") 41 | target_include_directories(png_static PRIVATE external/zlib "${CMAKE_CURRENT_BINARY_DIR}/external/zlib") 42 | target_link_libraries(png_static zlibstatic) 43 | add_dependencies(png_static zlibstatic) 44 | ############################################################################### 45 | # pkg-config path for dependencies 46 | include_directories("${CMAKE_CURRENT_SOURCE_DIR}/_deps/include") 47 | link_directories("${CMAKE_CURRENT_SOURCE_DIR}/_deps/lib") 48 | find_package(PkgConfig) 49 | pkg_check_modules(DAV1D REQUIRED dav1d) 50 | ############################################################################### 51 | 52 | add_executable(davif 53 | src/img/Conversion.cpp 54 | src/img/Conversion.hpp 55 | 56 | src/img/png/Writer.cpp 57 | src/img/png/Writer.hpp 58 | 59 | src/main.cpp 60 | ) 61 | 62 | # https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html#requiring-language-standards 63 | # https://stackoverflow.com/questions/45688522/how-to-enable-c17-in-cmake 64 | target_compile_features(davif PRIVATE cxx_std_17) 65 | # https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html 66 | set_property(TARGET davif PROPERTY CXX_STANDARD 17) 67 | set_property(TARGET davif PROPERTY CXX_STANDARD_REQUIRED ON) 68 | 69 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 70 | set_property(TARGET davif PROPERTY CXX_FLAGS_DEBUG "-g3 -O0 -fno-omit-frame-pointer") 71 | endif() 72 | 73 | target_include_directories(davif PRIVATE external/libpng) 74 | target_include_directories(davif PRIVATE "${CMAKE_BINARY_DIR}/include") 75 | target_include_directories(davif PRIVATE external/libavif-container/src) 76 | target_include_directories(davif PRIVATE external/libyuv/include) 77 | target_include_directories(davif PRIVATE ${DAV1D_INCLUDE_DIRS}) 78 | 79 | target_link_directories(davif PRIVATE "${CMAKE_BINARY_DIR}/lib") 80 | target_link_libraries(davif PRIVATE libavif-container) 81 | target_link_libraries(davif PRIVATE fmt::fmt) 82 | target_link_libraries(davif PRIVATE zlibstatic) 83 | target_link_libraries(davif PRIVATE png_static) 84 | target_link_libraries(davif PRIVATE pthread) 85 | target_link_libraries(davif PRIVATE dl) 86 | target_link_libraries(davif PRIVATE ${DAV1D_LDFLAGS} ${DAV1D_LIBRARIES}) 87 | 88 | ############################################################################### 89 | 90 | install(TARGETS davif 91 | RUNTIME DESTINATION bin 92 | ) 93 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019-present, Link-U Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # davif 2 | 3 | **Sorry, this repository is no longer maintained due to the retirement of the main maintainer. After some time, this repository will be archived.** 4 | 5 | **Ther source is currently maitained on avif-community by the maintaier. It's not a official community of AVIF codec. We take no resposibility the name of the community.** 6 | 7 | **This repository will be removed after 2023-01-31 to resolve the confusing situation.** 8 | 9 | 10 | | | Status | 11 | |--|---| 12 | | Linux | [![Build on Linux](https://github.com/link-u/davif/workflows/Build%20on%20Linux/badge.svg)](https://github.com/link-u/davif/actions?query=workflow%3A%22Build+on+Linux%22) | 13 | | Linux(.deb) | [![Build debian packages](https://github.com/link-u/davif/workflows/Build%20debian%20packages/badge.svg)](https://github.com/link-u/davif/actions?query=workflow%3A%22Build+debian+packages%22) | 14 | | macOS | [![Build on macOS](https://github.com/link-u/davif/workflows/Build%20on%20macOS/badge.svg)](https://github.com/link-u/davif/actions?query=workflow%3A%22Build+on+macOS%22) | 15 | | Windows | [![Build on Windows](https://github.com/link-u/davif/workflows/Build%20on%20Windows/badge.svg)](https://github.com/link-u/davif/actions?query=workflow%3A%22Build+on+Windows%22) | 16 | 17 | ## Description (en) 18 | 19 | avif decoder, using [dav1d](https://code.videolan.org/videolan/dav1d) directly. 20 | 21 | [avif (AV1 Image File Format)](https://aomediacodec.github.io/av1-avif/) is a still picture format uses a keyframe of [AV1](https://aomediacodec.github.io/av1-spec/av1-spec.pdf). 22 | 23 | ## Description (ja) 24 | 25 | [AVIF(AV1 Image File Format)]((https://aomediacodec.github.io/av1-avif/))は、動画フォーマットである[AV1](https://aomediacodec.github.io/av1-spec/av1-spec.pdf)のキーフレームを流用して圧縮する静止画フォーマットです。 26 | 27 | davifは、ラッパーを介さず[dav1d](https://code.videolan.org/videolan/dav1d)を直接叩くavifのデコード・コマンドです。 28 | 29 | ## how to build 30 | 31 | ```bash 32 | # pre-requirements 33 | # If your system cmake is lower than 3.13, please install latest version: 34 | # https://apt.kitware.com/ 35 | 36 | # cloning this repository with dependencies. 37 | git clone --recurse-submodules --recursive git@github.com:link-u/davif.git 38 | cd davif 39 | 40 | # Apply workarounds 41 | bash scripts/apply-patches.sh 42 | 43 | # Build dependencies not managed by CMake. 44 | bash scripts/build-deps.sh 45 | 46 | # System gcc is 8.0 or higher: 47 | cmake .. 48 | 49 | # If not, please install gcc-8 (or higher) and tell them to CMake. 50 | CXX=g++-8 CC=gcc-8 cmake .. 51 | 52 | # build davif binary. 53 | make davif 54 | 55 | # decode an avif image. 56 | ./davif -i input.avif -o output.png 57 | ``` 58 | 59 | ## usage 60 | 61 | ```bash 62 | % davif 63 | [2022/03/29 18:01:20 INFO ] davif 64 | [2022/03/29 18:01:20 INFO ] - dav1d ver: 1.0.0-0-g99172b1 65 | [2022/03/29 18:01:20 INFO ] - libpng ver: 1.6.38.git 66 | SYNOPSIS 67 | davif -i -o [--extract-alpha ] [--extract-depth 68 | ] [--threads ] 69 | 70 | davif -h 71 | 72 | OPTIONS 73 | -h, --help Show help and exit. 74 | ``` 75 | 76 | Example avif files are available in [AOMediaCodec/av1-avif](https://github.com/AOMediaCodec/av1-avif/tree/master/testFiles) or [link-u/avif-sample-images](https://github.com/link-u/avif-sample-images). 77 | 78 | (Currently, detailed documentation is only in [Japanese](./doc/ja_JP/README.md)) 79 | 80 | ## TODO 81 | 82 | - Add more and more command-line flags. 83 | 84 | # Related repositories 85 | 86 | - [link-u/cavif](https://github.com/link-u/cavif) - avif encoder, using libaom directly. 87 | - [link-u/libavif-container](https://github.com/link-u/libavif-container) - a library to parse avif container. 88 | - [link-u/avif-sample-images](https://github.com/link-u/avif-sample-images) - sample images from us. 89 | -------------------------------------------------------------------------------- /debian/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .debhelper 3 | files 4 | *.debhelper 5 | *.deb 6 | *.dsc 7 | *.build 8 | *.buildinfo 9 | *.changes 10 | *.tar.gz 11 | *.log 12 | *.substvars 13 | 14 | */ 15 | !source/ 16 | debhelper-build-stamp 17 | 18 | -------------------------------------------------------------------------------- /debian/README.Debian: -------------------------------------------------------------------------------- 1 | davif for Debian 2 | --------------- 3 | 4 | 5 | 6 | -- Ryo Hirafuji Sat, 25 Jan 2020 21:02:39 +0900 7 | -------------------------------------------------------------------------------- /debian/README.source: -------------------------------------------------------------------------------- 1 | davif for Debian 2 | --------------- 3 | 4 | 6 | 7 | 8 | 9 | -- Ryo Hirafuji Sat, 25 Jan 2020 21:02:39 +0900 10 | 11 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | davif (0.1.0) unstable; urgency=medium 2 | 3 | * Please see https://github.com/link-u/davif/releases for more information! 4 | 5 | -- Ryo Hirafuji Sat, 25 Jan 2020 21:02:39 +0900 6 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: davif 2 | Section: unknown 3 | Priority: optional 4 | Maintainer: Ryo Hirafuji 5 | Build-Depends: debhelper (>= 10), cmake (>= 3.13), pkg-config, gcc-9, g++-9, libc6-dev, libstdc++-9-dev, yasm, nasm 6 | Standards-Version: 4.1.2 7 | Homepage: https://github.com/link-u/davif 8 | Vcs-Git: https://github.com/link-u/davif.git 9 | Vcs-Browser: https://github.com/link-u/davif 10 | 11 | Package: davif 12 | Architecture: any 13 | Depends: ${shlibs:Depends}, ${misc:Depends} 14 | Description: avif decoder, using dav1d directly. 15 | An AVIF decoder. 16 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: davif 3 | Source: https://github.com/link-u/davif 4 | 5 | Files: * 6 | Copyright: 2019-present, Ryo Hirafuji at Link-U Inc. 7 | License: MIT 8 | The MIT License (MIT) 9 | 10 | Copyright (c) 2019-present, Link-U Inc. 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /debian/davif-docs.docs: -------------------------------------------------------------------------------- 1 | README.source 2 | README.Debian 3 | -------------------------------------------------------------------------------- /debian/davif.cron.d.ex: -------------------------------------------------------------------------------- 1 | # 2 | # Regular cron jobs for the davif package 3 | # 4 | 0 4 * * * root [ -x /usr/bin/davif_maintenance ] && /usr/bin/davif_maintenance 5 | -------------------------------------------------------------------------------- /debian/davif.doc-base.EX: -------------------------------------------------------------------------------- 1 | Document: davif 2 | Title: Debian davif Manual 3 | Author: 4 | Abstract: This manual describes what davif is 5 | and how it can be used to 6 | manage online manuals on Debian systems. 7 | Section: unknown 8 | 9 | Format: debiandoc-sgml 10 | Files: /usr/share/doc/davif/davif.sgml.gz 11 | 12 | Format: postscript 13 | Files: /usr/share/doc/davif/davif.ps.gz 14 | 15 | Format: text 16 | Files: /usr/share/doc/davif/davif.text.gz 17 | 18 | Format: HTML 19 | Index: /usr/share/doc/davif/html/index.html 20 | Files: /usr/share/doc/davif/html/*.html 21 | -------------------------------------------------------------------------------- /debian/manpage.1.ex: -------------------------------------------------------------------------------- 1 | .\" Hey, EMACS: -*- nroff -*- 2 | .\" (C) Copyright 2020 Ryo Hirafuji , 3 | .\" 4 | .\" First parameter, NAME, should be all caps 5 | .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection 6 | .\" other parameters are allowed: see man(7), man(1) 7 | .TH Davif SECTION "January 25 2020" 8 | .\" Please adjust this date whenever revising the manpage. 9 | .\" 10 | .\" Some roff macros, for reference: 11 | .\" .nh disable hyphenation 12 | .\" .hy enable hyphenation 13 | .\" .ad l left justify 14 | .\" .ad b justify to both left and right margins 15 | .\" .nf disable filling 16 | .\" .fi enable filling 17 | .\" .br insert line break 18 | .\" .sp insert n+1 empty lines 19 | .\" for manpage-specific macros, see man(7) 20 | .SH NAME 21 | davif \- program to do something 22 | .SH SYNOPSIS 23 | .B davif 24 | .RI [ options ] " files" ... 25 | .br 26 | .B bar 27 | .RI [ options ] " files" ... 28 | .SH DESCRIPTION 29 | This manual page documents briefly the 30 | .B davif 31 | and 32 | .B bar 33 | commands. 34 | .PP 35 | .\" TeX users may be more comfortable with the \fB\fP and 36 | .\" \fI\fP escape sequences to invode bold face and italics, 37 | .\" respectively. 38 | \fBdavif\fP is a program that... 39 | .SH OPTIONS 40 | These programs follow the usual GNU command line syntax, with long 41 | options starting with two dashes (`-'). 42 | A summary of options is included below. 43 | For a complete description, see the Info files. 44 | .TP 45 | .B \-h, \-\-help 46 | Show summary of options. 47 | .TP 48 | .B \-v, \-\-version 49 | Show version of program. 50 | .SH SEE ALSO 51 | .BR bar (1), 52 | .BR baz (1). 53 | .br 54 | The programs are documented fully by 55 | .IR "The Rise and Fall of a Fooish Bar" , 56 | available via the Info system. 57 | -------------------------------------------------------------------------------- /debian/manpage.sgml.ex: -------------------------------------------------------------------------------- 1 | manpage.1'. You may view 5 | the manual page with: `docbook-to-man manpage.sgml | nroff -man | 6 | less'. A typical entry in a Makefile or Makefile.am is: 7 | 8 | manpage.1: manpage.sgml 9 | docbook-to-man $< > $@ 10 | 11 | 12 | The docbook-to-man binary is found in the docbook-to-man package. 13 | Please remember that if you create the nroff version in one of the 14 | debian/rules file targets (such as build), you will need to include 15 | docbook-to-man in your Build-Depends control field. 16 | 17 | --> 18 | 19 | 20 | FIRSTNAME"> 21 | SURNAME"> 22 | 23 | January 25 2020"> 24 | 26 | SECTION"> 27 | ryo.hirafuji@link-u.co.jp"> 28 | 29 | Davif"> 30 | 31 | 32 | Debian"> 33 | GNU"> 34 | GPL"> 35 | ]> 36 | 37 | 38 | 39 |
40 | &dhemail; 41 |
42 | 43 | &dhfirstname; 44 | &dhsurname; 45 | 46 | 47 | 2003 48 | &dhusername; 49 | 50 | &dhdate; 51 |
52 | 53 | &dhucpackage; 54 | 55 | &dhsection; 56 | 57 | 58 | &dhpackage; 59 | 60 | program to do something 61 | 62 | 63 | 64 | &dhpackage; 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | DESCRIPTION 73 | 74 | This manual page documents briefly the 75 | &dhpackage; and bar 76 | commands. 77 | 78 | This manual page was written for the &debian; distribution 79 | because the original program does not have a manual page. 80 | Instead, it has documentation in the &gnu; 81 | Info format; see below. 82 | 83 | &dhpackage; is a program that... 84 | 85 | 86 | 87 | OPTIONS 88 | 89 | These programs follow the usual &gnu; command line syntax, 90 | with long options starting with two dashes (`-'). A summary of 91 | options is included below. For a complete description, see the 92 | Info files. 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | Show summary of options. 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | Show version of program. 109 | 110 | 111 | 112 | 113 | 114 | SEE ALSO 115 | 116 | bar (1), baz (1). 117 | 118 | The programs are documented fully by The Rise and 119 | Fall of a Fooish Bar available via the 120 | Info system. 121 | 122 | 123 | AUTHOR 124 | 125 | This manual page was written by &dhusername; &dhemail; for 126 | the &debian; system (and may be used by others). Permission is 127 | granted to copy, distribute and/or modify this document under 128 | the terms of the &gnu; General Public License, Version 2 any 129 | later version published by the Free Software Foundation. 130 | 131 | 132 | On Debian systems, the complete text of the GNU General Public 133 | License can be found in /usr/share/common-licenses/GPL. 134 | 135 | 136 | 137 |
138 | 139 | 155 | -------------------------------------------------------------------------------- /debian/manpage.xml.ex: -------------------------------------------------------------------------------- 1 | 2 | .
will be generated. You may view the 15 | manual page with: nroff -man .
| less'. A typical entry 16 | in a Makefile or Makefile.am is: 17 | 18 | DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl 19 | XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" 20 | 21 | manpage.1: manpage.xml 22 | $(XP) $(DB2MAN) $< 23 | 24 | The xsltproc binary is found in the xsltproc package. The XSL files are in 25 | docbook-xsl. A description of the parameters you can use can be found in the 26 | docbook-xsl-doc-* packages. Please remember that if you create the nroff 27 | version in one of the debian/rules file targets (such as build), you will need 28 | to include xsltproc and docbook-xsl in your Build-Depends control field. 29 | Alternatively use the xmlto command/package. That will also automatically 30 | pull in xsltproc and docbook-xsl. 31 | 32 | Notes for using docbook2x: docbook2x-man does not automatically create the 33 | AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as 34 | ... . 35 | 36 | To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections 37 | read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be 38 | found in the docbook-xsl-doc-html package. 39 | 40 | Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` 41 | 42 | General documentation about man-pages and man-page-formatting: 43 | man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ 44 | 45 | --> 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 56 | 57 | 59 | 60 | 61 | 62 | ]> 63 | 64 | 65 | 66 | &dhtitle; 67 | &dhpackage; 68 | 69 | 70 | &dhfirstname; 71 | &dhsurname; 72 | Wrote this manpage for the Debian system. 73 |
74 | &dhemail; 75 |
76 |
77 |
78 | 79 | 2007 80 | &dhusername; 81 | 82 | 83 | This manual page was written for the Debian system 84 | (and may be used by others). 85 | Permission is granted to copy, distribute and/or modify this 86 | document under the terms of the GNU General Public License, 87 | Version 2 or (at your option) any later version published by 88 | the Free Software Foundation. 89 | On Debian systems, the complete text of the GNU General Public 90 | License can be found in 91 | /usr/share/common-licenses/GPL. 92 | 93 |
94 | 95 | &dhucpackage; 96 | &dhsection; 97 | 98 | 99 | &dhpackage; 100 | program to do something 101 | 102 | 103 | 104 | &dhpackage; 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | this 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | this 122 | that 123 | 124 | 125 | 126 | 127 | &dhpackage; 128 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | DESCRIPTION 148 | This manual page documents briefly the 149 | &dhpackage; and bar 150 | commands. 151 | This manual page was written for the Debian distribution 152 | because the original program does not have a manual page. 153 | Instead, it has documentation in the GNU 154 | info 155 | 1 156 | format; see below. 157 | &dhpackage; is a program that... 158 | 159 | 160 | OPTIONS 161 | The program follows the usual GNU command line syntax, 162 | with long options starting with two dashes (`-'). A summary of 163 | options is included below. For a complete description, see the 164 | 165 | info 166 | 1 167 | files. 168 | 169 | 172 | 173 | 174 | 175 | 176 | Does this and that. 177 | 178 | 179 | 180 | 181 | 182 | 183 | Show summary of options. 184 | 185 | 186 | 187 | 188 | 189 | 190 | Show version of program. 191 | 192 | 193 | 194 | 195 | 196 | FILES 197 | 198 | 199 | /etc/foo.conf 200 | 201 | The system-wide configuration file to control the 202 | behaviour of &dhpackage;. See 203 | 204 | foo.conf 205 | 5 206 | for further details. 207 | 208 | 209 | 210 | ${HOME}/.foo.conf 211 | 212 | The per-user configuration file to control the 213 | behaviour of &dhpackage;. See 214 | 215 | foo.conf 216 | 5 217 | for further details. 218 | 219 | 220 | 221 | 222 | 223 | ENVIRONMENT 224 | 225 | 226 | FOO_CONF 227 | 228 | If used, the defined file is used as configuration 229 | file (see also ). 230 | 231 | 232 | 233 | 234 | 235 | DIAGNOSTICS 236 | The following diagnostics may be issued 237 | on stderr: 238 | 239 | 240 | Bad configuration file. Exiting. 241 | 242 | The configuration file seems to contain a broken configuration 243 | line. Use the option, to get more info. 244 | 245 | 246 | 247 | 248 | &dhpackage; provides some return codes, that can 249 | be used in scripts: 250 | 251 | Code 252 | Diagnostic 253 | 254 | 0 255 | Program exited successfully. 256 | 257 | 258 | 1 259 | The configuration file seems to be broken. 260 | 261 | 262 | 263 | 264 | 265 | BUGS 266 | The program is currently limited to only work 267 | with the foobar library. 268 | The upstreams BTS can be found 269 | at . 270 | 271 | 272 | SEE ALSO 273 | 274 | 275 | bar 276 | 1 277 | , 278 | baz 279 | 1 280 | , 281 | foo.conf 282 | 5 283 | 284 | The programs are documented fully by The Rise and 285 | Fall of a Fooish Bar available via the 286 | info 287 | 1 288 | system. 289 | 290 |
291 | 292 | -------------------------------------------------------------------------------- /debian/menu.ex: -------------------------------------------------------------------------------- 1 | ?package(davif):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\ 2 | title="davif" command="/usr/bin/davif" 3 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # See debhelper(7) (uncomment to enable) 3 | # output every command that modifies files on the build system. 4 | #export DH_VERBOSE = 1 5 | 6 | 7 | # see FEATURE AREAS in dpkg-buildflags(1) 8 | #export DEB_BUILD_MAINT_OPTIONS = hardening=+all 9 | 10 | # see ENVIRONMENT in dpkg-buildflags(1) 11 | # package maintainers to append CFLAGS 12 | #export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic 13 | # package maintainers to append LDFLAGS 14 | #export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed 15 | 16 | 17 | %: 18 | dh $@ --builddirectory=build 19 | 20 | 21 | # dh_make generated override targets 22 | # This is example for Cmake (See https://bugs.debian.org/641051 ) 23 | #override_dh_auto_configure: 24 | # dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) 25 | override_dh_auto_configure: 26 | dh_auto_configure -- 27 | override_dh_builddeb: 28 | dh_builddeb --destdir=. 29 | 30 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/watch.ex: -------------------------------------------------------------------------------- 1 | # Example watch control file for uscan 2 | # Rename this file to "watch" and then you can run the "uscan" command 3 | # to check for upstream updates and more. 4 | # See uscan(1) for format 5 | 6 | # Compulsory line, this is a version 4 file 7 | version=4 8 | 9 | # PGP signature mangle, so foo.tar.gz has foo.tar.gz.sig 10 | #opts="pgpsigurlmangle=s%$%.sig%" 11 | 12 | # HTTP site (basic) 13 | #http://example.com/downloads.html \ 14 | # files/davif-([\d\.]+)\.tar\.gz debian uupdate 15 | 16 | # Uncomment to examine an FTP server 17 | #ftp://ftp.example.com/pub/davif-(.*)\.tar\.gz debian uupdate 18 | 19 | # SourceForge hosted projects 20 | # http://sf.net/davif/ davif-(.*)\.tar\.gz debian uupdate 21 | 22 | # GitHub hosted projects 23 | #opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%-$1.tar.gz%" \ 24 | # https://github.com//davif/tags \ 25 | # (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate 26 | 27 | # PyPI 28 | # https://pypi.debian.net/davif/davif-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) 29 | 30 | # Direct Git 31 | # opts="mode=git" http://git.example.com/davif.git \ 32 | # refs/tags/v([\d\.]+) debian uupdate 33 | 34 | 35 | 36 | 37 | # Uncomment to find new files on GooglePages 38 | # http://example.googlepages.com/foo.html davif-(.*)\.tar\.gz 39 | -------------------------------------------------------------------------------- /doc/ja_JP/README.md: -------------------------------------------------------------------------------- 1 | # davif ドキュメント 2 | 3 | - [コマンドラインオプション](usage.md) 4 | 5 | ## 参考になるかもしれないリンク集 6 | 7 | - [AV1 Image File Format (AVIF)](https://people.xiph.org/~negge/AVIF2018.pdf) 8 | - [dav1d](https://code.videolan.org/videolan/dav1d) 9 | - [dav1d/wiki](https://code.videolan.org/videolan/dav1d/-/wikis/home) 10 | 11 | ## サンプルファイル 12 | 13 | - [AOMediaCodec/av1-avif](https://github.com/AOMediaCodec/av1-avif/tree/master/testFiles) 14 | - [link-u/avif-sample-images](https://github.com/link-u/avif-sample-images) 15 | -------------------------------------------------------------------------------- /doc/ja_JP/usage.md: -------------------------------------------------------------------------------- 1 | # コマンドラインオプションの説明 2 | 3 | ## 入出力 4 | 5 | ### 入力 6 | 7 | - `-i input.avif`(必須) 8 | 9 | ### 出力 10 | 11 | - `-o output.png`(必須) 12 | 13 | ### Alpha/Depth画像の展開 14 | 15 | - `--extract-alpha ` 16 | - `--extract-depth ` 17 | 18 | 付与されているalpha/depthの画像を別ファイルにデコードして保存する。 19 | 20 | このオプションでalphaを展開しても、`-o `で指定したファイルには引き続きalphaは適用される。 21 | 22 | ## マルチスレッド 23 | 24 | ### 利用スレッド数 25 | 26 | - `--threads ` 27 | - 初期値:論理コア数(`nproc`コマンドで確認可能) 28 | 29 | 注意点: 30 | 31 | - `--threads 0` の場合、メインスレッドのみでデコードする。 32 | - `--threads 1` の場合、メインスレッドとは別にもう1つスレッドが建ち、一応多少早くなる。 33 | -------------------------------------------------------------------------------- /patches/zlib.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 0fe939d..e6363b7 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -230,20 +230,20 @@ endif() 6 | # Example binaries 7 | #============================================================================ 8 | 9 | -add_executable(example test/example.c) 10 | -target_link_libraries(example zlib) 11 | -add_test(example example) 12 | - 13 | -add_executable(minigzip test/minigzip.c) 14 | -target_link_libraries(minigzip zlib) 15 | - 16 | -if(HAVE_OFF64_T) 17 | - add_executable(example64 test/example.c) 18 | - target_link_libraries(example64 zlib) 19 | - set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") 20 | - add_test(example64 example64) 21 | - 22 | - add_executable(minigzip64 test/minigzip.c) 23 | - target_link_libraries(minigzip64 zlib) 24 | - set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") 25 | -endif() 26 | +#add_executable(example test/example.c) 27 | +#target_link_libraries(example zlib) 28 | +#add_test(example example) 29 | +# 30 | +#add_executable(minigzip test/minigzip.c) 31 | +#target_link_libraries(minigzip zlib) 32 | +# 33 | +#if(HAVE_OFF64_T) 34 | +# add_executable(example64 test/example.c) 35 | +# target_link_libraries(example64 zlib) 36 | +# set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") 37 | +# add_test(example64 example64) 38 | +# 39 | +# add_executable(minigzip64 test/minigzip.c) 40 | +# target_link_libraries(minigzip64 zlib) 41 | +# set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") 42 | +#endif() 43 | -------------------------------------------------------------------------------- /scripts/apply-patches.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | function readlink_f() { 4 | local src='import os,sys;print(os.path.realpath(sys.argv[1]))' 5 | python3 -c "${src}" "$1" || python -c "${src}" "$1" 6 | } 7 | 8 | ROOT_DIR="$(cd "$(readlink_f "$(dirname "$0")")" && cd .. && pwd)" 9 | cd "${ROOT_DIR}" || exit 1 10 | 11 | set -eux 12 | set -o pipefail 13 | 14 | (cd external/zlib; patch -p1 --forward < ../../patches/zlib.patch || true) 15 | -------------------------------------------------------------------------------- /scripts/build-debian-package.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | set -eux 4 | 5 | function readlink_f() { 6 | local src='import os,sys;print(os.path.realpath(sys.argv[1]))' 7 | python3 -c "${src}" "$1" || python -c "${src}" "$1" 8 | } 9 | 10 | ROOT_DIR="$(cd "$(readlink_f "$(dirname "$0")")" && cd .. && pwd)" 11 | cd "${ROOT_DIR}" || exit 1 12 | 13 | # To avoid limitation: 14 | # https://git-scm.com/docs/git-config/2.35.2#Documentation/git-config.txt-safedirectory 15 | chown "$(id -g):$(id -u)" . -R 16 | 17 | # Generate changelog 18 | git_describe="$(git describe --tags)" 19 | VERSION=${git_describe:1}.$(TZ=JST-9 date +%Y%m%d)+$(lsb_release -cs) 20 | DATE=$(LC_ALL=C TZ=JST-9 date '+%a, %d %b %Y %H:%M:%S %z') 21 | 22 | cat < "${ROOT_DIR}/debian/changelog" 23 | davif (${VERSION}) unstable; urgency=medium 24 | 25 | * This is atomated build. 26 | * Please see https://github.com/link-u/davif/releases for more information! 27 | 28 | -- Ryo Hirafuji ${DATE} 29 | EOF 30 | 31 | # Add Kitware APT repository to install the latest cmake. 32 | # https://apt.kitware.com/ 33 | apt-get update 34 | apt-get install -y --no-install-recommends apt-transport-https ca-certificates gnupg software-properties-common wget 35 | wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null 36 | apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" 37 | 38 | # Workaround: gcc >= 8.0 is required. 39 | case $(lsb_release -cs) in 40 | bionic) 41 | export CC=gcc-8 42 | export CXX=g++-8 43 | sed -i -r "s/gcc-9/gcc-8/g" "${ROOT_DIR}/debian/control" 44 | sed -i -r "s/g\+\+-9/g++-8/g" "${ROOT_DIR}/debian/control" 45 | sed -i -r "s/libstdc\+\+-9-dev/libstdc++-8-dev/g" "${ROOT_DIR}/debian/control" 46 | # bionic's nasm is too old. 47 | sed -i -e 's/-Denable_asm=true/-Denable_asm=false/g' scripts/build-deps.sh 48 | ;; 49 | *) ;; 50 | esac 51 | 52 | # Workaround: meson has been upgraded so fast, we use the latest versions. 53 | apt-get install -y --no-install-recommends python3-venv python3-pip python3-setuptools 54 | python3 -m venv venv 55 | source venv/bin/activate 56 | pip3 install wheel 57 | pip3 install meson ninja 58 | 59 | # Install deps to build. 60 | mk-build-deps --install --remove \ 61 | --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' \ 62 | "${ROOT_DIR}/debian/control" 63 | 64 | bash scripts/reset-submodules.sh 65 | bash scripts/apply-patches.sh 66 | bash scripts/build-deps.sh 67 | 68 | fakeroot debian/rules clean 69 | fakeroot debian/rules build 70 | fakeroot debian/rules binary 71 | # workaround. external/libpng will be dirty after making debian packages. 72 | env --chdir=external/libpng git reset --hard 73 | -------------------------------------------------------------------------------- /scripts/build-deps.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -eux 2 | 3 | function readlink_f() { 4 | local src='import os,sys;print(os.path.realpath(sys.argv[1]))' 5 | python3 -c "${src}" "$1" || python -c "${src}" "$1" 6 | } 7 | 8 | ROOT_DIR="$(cd "$(readlink_f "$(dirname "$0")")" && cd .. && pwd)" 9 | cd "${ROOT_DIR}" || exit 1 10 | 11 | set -eux 12 | set -o pipefail 13 | 14 | DEPS_DIR="$(readlink_f "${ROOT_DIR}/_deps")" 15 | 16 | rm -Rf "${DEPS_DIR}" 17 | mkdir -p "${DEPS_DIR}" 18 | 19 | # dav1d 20 | bash -eux < 6 | #include 7 | #include "Conversion.hpp" 8 | 9 | namespace img { 10 | 11 | template 12 | void writeImage(avif::img::Image& dst, Dav1dPicture& src) { 13 | switch (src.p.layout) { 14 | case DAV1D_PIXEL_LAYOUT_I400: 15 | avif::img::ToRGB::fromI400(dst, 16 | reinterpret_cast(src.data[0]), 17 | src.stride[0]); 18 | break; 19 | case DAV1D_PIXEL_LAYOUT_I420: 20 | avif::img::ToRGB::fromI420(dst, 21 | reinterpret_cast(src.data[0]), 22 | src.stride[0], 23 | reinterpret_cast(src.data[1]), 24 | src.stride[1], 25 | reinterpret_cast(src.data[2]), 26 | src.stride[1]); 27 | break; 28 | case DAV1D_PIXEL_LAYOUT_I422: 29 | avif::img::ToRGB::fromI422(dst, 30 | reinterpret_cast(src.data[0]), 31 | src.stride[0], 32 | reinterpret_cast(src.data[1]), 33 | src.stride[1], 34 | reinterpret_cast(src.data[2]), 35 | src.stride[1]); 36 | break; 37 | case DAV1D_PIXEL_LAYOUT_I444: 38 | avif::img::ToRGB::fromI444(dst, 39 | reinterpret_cast(src.data[0]), 40 | src.stride[0], 41 | reinterpret_cast(src.data[1]), 42 | src.stride[1], 43 | reinterpret_cast(src.data[2]), 44 | src.stride[1]); 45 | break; 46 | } 47 | } 48 | 49 | template 50 | void writeImage(avif::img::Image &dst, Dav1dPicture &src) { 51 | if (src.seq_hdr->color_range == 0) { 52 | writeImage(dst, src); 53 | } else { 54 | writeImage(dst, src); 55 | } 56 | 57 | } 58 | 59 | template 60 | void writeAlpha(avif::img::Image& dst, Dav1dPicture& src) { 61 | switch (src.p.layout) { 62 | case DAV1D_PIXEL_LAYOUT_I400: 63 | avif::img::ToAlpha::fromI400(dst, 64 | reinterpret_cast(src.data[0]), 65 | src.stride[0]); 66 | break; 67 | default: 68 | throw std::domain_error("Alpha image must be monochrome"); 69 | } 70 | } 71 | 72 | template 73 | avif::img::Image convertToRGB(Dav1dPicture& primary) { 74 | avif::img::PixelOrder const pixelOrder = 75 | primary.p.layout == DAV1D_PIXEL_LAYOUT_I400 ? 76 | avif::img::PixelOrder::Mono : 77 | avif::img::PixelOrder::RGB; 78 | 79 | avif::img::Image img = avif::img::Image::createEmptyImage(pixelOrder, primary.p.w, primary.p.h); 80 | 81 | if (img.isMonochrome()) { 82 | writeImage(img, primary); 83 | } else { 84 | writeImage(img, primary); 85 | } 86 | return img; 87 | } 88 | 89 | template 90 | avif::img::Image 91 | convertToRGBA(Dav1dPicture& primary, Dav1dPicture& alpha) { 92 | avif::img::PixelOrder const pixelOrder = 93 | primary.p.layout == DAV1D_PIXEL_LAYOUT_I400 ? avif::img::PixelOrder::MonoA : avif::img::PixelOrder::RGBA; 94 | avif::img::Image img = avif::img::Image::createEmptyImage(pixelOrder, primary.p.w, primary.p.h); 95 | 96 | if (primary.seq_hdr->color_range == 0) { 97 | writeImage(img, primary); 98 | } else { 99 | writeImage(img, primary); 100 | } 101 | 102 | if (alpha.seq_hdr->color_range == 0) { 103 | writeAlpha(img, alpha); 104 | } else { 105 | writeAlpha( img, alpha); 106 | } 107 | return img; 108 | } 109 | 110 | template 111 | avif::img::Image 112 | convertToRGBA(Dav1dPicture& primary, Dav1dPicture& alpha) { 113 | switch (alpha.p.bpc) { 114 | case 8: 115 | return convertToRGBA(primary, alpha); 116 | case 10: 117 | return convertToRGBA(primary, alpha); 118 | case 12: 119 | return convertToRGBA(primary, alpha); 120 | default: 121 | throw std::runtime_error(fmt::format("Unknwon alpha bpc={}", alpha.p.bpc)); 122 | } 123 | } 124 | 125 | template 126 | std::variant, avif::img::Image<16>> 127 | createImageRGB(Dav1dPicture& primary) { 128 | switch (primary.p.bpc) { 129 | case 8: 130 | return convertToRGB(primary); 131 | case 10: 132 | return convertToRGB(primary); 133 | case 12: 134 | return convertToRGB(primary); 135 | default: 136 | throw std::runtime_error(fmt::format("Unknwon bpc={}", primary.p.bpc)); 137 | } 138 | } 139 | 140 | template 141 | std::variant, avif::img::Image<16>> 142 | createImageRGBA(Dav1dPicture& primary, Dav1dPicture& alpha) { 143 | if (primary.p.bpc == 8 && alpha.p.bpc == 8) { 144 | switch (primary.p.bpc) { 145 | case 8: 146 | return convertToRGBA(primary, alpha); 147 | case 10: 148 | return convertToRGBA(primary, alpha); 149 | case 12: 150 | return convertToRGBA(primary, alpha); 151 | default: 152 | throw std::runtime_error(fmt::format("Unknwon bpc={}", primary.p.bpc)); 153 | } 154 | } else { 155 | switch (primary.p.bpc) { 156 | case 8: 157 | return convertToRGBA(primary, alpha); 158 | case 10: 159 | return convertToRGBA(primary, alpha); 160 | case 12: 161 | return convertToRGBA(primary, alpha); 162 | default: 163 | throw std::runtime_error(fmt::format("Unknwon bpc={}", primary.p.bpc)); 164 | } 165 | } 166 | } 167 | 168 | template 169 | std::variant< 170 | avif::img::Image<8>, 171 | avif::img::Image<16> 172 | > createImage( 173 | Dav1dPicture& primary, 174 | std::optional> alpha 175 | ) { 176 | using avif::img::color::ColorConverter; 177 | if (!alpha.has_value()) { 178 | return createImageRGB(primary); 179 | } 180 | 181 | auto const& [alphaPic, alphaProf] = alpha.value(); 182 | 183 | avif::ColourInformationBox::CICP cicp; 184 | if(alphaProf.cicp.has_value()) { 185 | cicp = alphaProf.cicp.value(); 186 | } 187 | using avif::img::color::MatrixCoefficients; 188 | switch (static_cast(cicp.matrixCoefficients)) { 189 | case MatrixCoefficients::MC_IDENTITY: { 190 | using Converter = avif::img::color::ColorConverter; 191 | return createImageRGBA(primary, alphaPic); 192 | } 193 | case MatrixCoefficients::MC_BT_709: { 194 | using Converter = avif::img::color::ColorConverter; 195 | return createImageRGBA(primary, alphaPic); 196 | } 197 | case MatrixCoefficients::MC_FCC: { 198 | using Converter = avif::img::color::ColorConverter; 199 | return createImageRGBA(primary, alphaPic); 200 | } 201 | case MatrixCoefficients::MC_UNSPECIFIED: 202 | case MatrixCoefficients::MC_BT_470_B_G: { 203 | using Converter = avif::img::color::ColorConverter; 204 | return createImageRGBA(primary, alphaPic); 205 | } 206 | case MatrixCoefficients::MC_NSTC: { 207 | using Converter = avif::img::color::ColorConverter; 208 | return createImageRGBA(primary, alphaPic); 209 | } 210 | case MatrixCoefficients::MC_SMPTE_240: { 211 | using Converter = avif::img::color::ColorConverter; 212 | return createImageRGBA(primary, alphaPic); 213 | } 214 | case MatrixCoefficients::MC_SMPTE_YCGCO: { 215 | using Converter = avif::img::color::ColorConverter; 216 | return createImageRGBA(primary, alphaPic); 217 | } 218 | case MatrixCoefficients::MC_BT_2020_NCL: { 219 | using Converter = avif::img::color::ColorConverter; 220 | return createImageRGBA(primary, alphaPic); 221 | } 222 | case MatrixCoefficients::MC_BT_2020_CL: { 223 | using Converter = avif::img::color::ColorConverter; 224 | return createImageRGBA(primary, alphaPic); 225 | } 226 | case MatrixCoefficients::MC_SMPTE_2085: { 227 | using Converter = avif::img::color::ColorConverter; 228 | return createImageRGBA(primary, alphaPic); 229 | } 230 | case MatrixCoefficients::MC_CHROMAT_NCL: { 231 | using Converter = avif::img::color::ColorConverter; 232 | return createImageRGBA(primary, alphaPic); 233 | } 234 | case MatrixCoefficients::MC_CHROMAT_CL: { 235 | using Converter = avif::img::color::ColorConverter; 236 | return createImageRGBA(primary, alphaPic); 237 | } 238 | case MatrixCoefficients::MC_BT_2100_ICTCP: { 239 | using Converter = avif::img::color::ColorConverter; 240 | return createImageRGBA(primary, alphaPic); 241 | } 242 | default: 243 | assert(false && "Unknown matrix coefficients"); 244 | } 245 | } 246 | 247 | std::variant< 248 | avif::img::Image<8>, 249 | avif::img::Image<16> 250 | > createImage( 251 | Dav1dPicture& primary, avif::img::ColorProfile const& primaryProfile, 252 | std::optional> alpha 253 | ) { 254 | 255 | avif::ColourInformationBox::CICP cicp = {}; 256 | if(primaryProfile.cicp.has_value()) { 257 | cicp = primaryProfile.cicp.value(); 258 | } 259 | 260 | using avif::img::color::MatrixCoefficients; 261 | switch (static_cast(cicp.matrixCoefficients)) { 262 | case MatrixCoefficients::MC_IDENTITY: { 263 | using Converter = avif::img::color::ColorConverter; 264 | return createImage(primary, alpha); 265 | } 266 | case MatrixCoefficients::MC_BT_709: { 267 | using Converter = avif::img::color::ColorConverter; 268 | return createImage(primary, alpha); 269 | } 270 | case MatrixCoefficients::MC_FCC: { 271 | using Converter = avif::img::color::ColorConverter; 272 | return createImage(primary, alpha); 273 | } 274 | case MatrixCoefficients::MC_UNSPECIFIED: 275 | case MatrixCoefficients::MC_BT_470_B_G: { 276 | using Converter = avif::img::color::ColorConverter; 277 | return createImage(primary, alpha); 278 | } 279 | case MatrixCoefficients::MC_NSTC: { 280 | using Converter = avif::img::color::ColorConverter; 281 | return createImage(primary, alpha); 282 | } 283 | case MatrixCoefficients::MC_SMPTE_240: { 284 | using Converter = avif::img::color::ColorConverter; 285 | return createImage(primary, alpha); 286 | } 287 | case MatrixCoefficients::MC_SMPTE_YCGCO: { 288 | using Converter = avif::img::color::ColorConverter; 289 | return createImage(primary, alpha); 290 | } 291 | case MatrixCoefficients::MC_BT_2020_NCL: { 292 | using Converter = avif::img::color::ColorConverter; 293 | return createImage(primary, alpha); 294 | } 295 | case MatrixCoefficients::MC_BT_2020_CL: { 296 | using Converter = avif::img::color::ColorConverter; 297 | return createImage(primary, alpha); 298 | } 299 | case MatrixCoefficients::MC_SMPTE_2085: { 300 | using Converter = avif::img::color::ColorConverter; 301 | return createImage(primary, alpha); 302 | } 303 | case MatrixCoefficients::MC_CHROMAT_NCL: { 304 | using Converter = avif::img::color::ColorConverter; 305 | return createImage(primary, alpha); 306 | } 307 | case MatrixCoefficients::MC_CHROMAT_CL: { 308 | using Converter = avif::img::color::ColorConverter; 309 | return createImage(primary, alpha); 310 | } 311 | case MatrixCoefficients::MC_BT_2100_ICTCP: { 312 | using Converter = avif::img::color::ColorConverter; 313 | return createImage(primary, alpha); 314 | } 315 | default: 316 | assert(false && "Unknown matrix coefficients"); 317 | } 318 | } 319 | 320 | } 321 | -------------------------------------------------------------------------------- /src/img/Conversion.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by psi on 2020/02/16. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace img { 14 | 15 | std::variant< 16 | avif::img::Image<8>, 17 | avif::img::Image<16> 18 | > createImage( 19 | Dav1dPicture& primary, avif::img::ColorProfile const& primaryProfile, 20 | std::optional> alpha 21 | ); 22 | 23 | } -------------------------------------------------------------------------------- /src/img/png/Writer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by psi on 2020/02/16. 3 | // 4 | 5 | #include "Writer.hpp" 6 | 7 | namespace img::png { 8 | 9 | void Writer::png_write_callback_(png_structp png_ptr, png_bytep data, png_size_t length) { 10 | auto buff = reinterpret_cast(png_get_io_ptr(png_ptr)); 11 | buff->append(data, length); 12 | } 13 | 14 | char const *Writer::version() { 15 | return PNG_LIBPNG_VER_STRING; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/img/png/Writer.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by psi on 2020/02/16. 3 | // 4 | 5 | #pragma once 6 | 7 | 8 | #include 9 | #include "avif/util/Logger.hpp" 10 | #include "avif/img/Image.hpp" 11 | #include "png.h" 12 | #include "avif/util/File.hpp" 13 | #include "avif/util/StreamWriter.hpp" 14 | 15 | namespace img::png { 16 | 17 | class Writer final { 18 | private: 19 | avif::util::Logger& log_; 20 | std::string filename_; 21 | public: 22 | Writer() = delete; 23 | Writer(Writer const&) = delete; 24 | Writer(Writer&&) = delete; 25 | Writer& operator=(Writer const&) = delete; 26 | Writer& operator=(Writer&&) = delete; 27 | ~Writer() noexcept = default; 28 | public: 29 | explicit Writer(avif::util::Logger& log, std::string filename) noexcept 30 | :log_(log) 31 | ,filename_(std::move(filename)){ 32 | } 33 | static char const* version(); 34 | template 35 | std::optional write(avif::img::Image& img) { 36 | //FIXME(ledyba-z): add error handling 37 | const size_t w = img.width(); 38 | const size_t h = img.height(); 39 | const size_t stride = img.stride(); 40 | png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); 41 | png_infop info = png_create_info_struct(png); 42 | int color_type = PNG_COLOR_TYPE_GRAY; 43 | switch(img.pixelOrder()) { 44 | case avif::img::PixelOrder::RGB: 45 | color_type = PNG_COLOR_TYPE_RGB; 46 | break; 47 | case avif::img::PixelOrder::RGBA: 48 | color_type = PNG_COLOR_TYPE_RGB_ALPHA; 49 | break; 50 | case avif::img::PixelOrder::Mono: 51 | color_type = PNG_COLOR_TYPE_GRAY; 52 | break; 53 | case avif::img::PixelOrder::MonoA: 54 | color_type = PNG_COLOR_TYPE_GRAY_ALPHA; 55 | break; 56 | } 57 | png_set_IHDR(png, info, w, h, BitsPerComponent, 58 | color_type, 59 | PNG_INTERLACE_NONE, 60 | PNG_COMPRESSION_TYPE_DEFAULT, 61 | PNG_FILTER_TYPE_DEFAULT); 62 | auto const& colorProfile = img.colorProfile(); 63 | 64 | if(colorProfile.iccProfile.has_value()){ 65 | avif::img::ICCProfile const& icc = colorProfile.iccProfile.value(); 66 | png_set_benign_errors(png, 1); 67 | png_set_iCCP(png, info, "ICC Profile", 0, icc.payload().data(), icc.payload().size()); 68 | png_set_benign_errors(png, 0); 69 | } else if(colorProfile.cicp.has_value()) { 70 | avif::ColourInformationBox::CICP const& cicp = colorProfile.cicp.value(); 71 | if (cicp.colourPrimaries == 1 && cicp.transferCharacteristics == 13) { 72 | // TODO(ledyba-z): How about intent? 73 | png_set_sRGB_gAMA_and_cHRM(png, info, PNG_sRGB_INTENT_PERCEPTUAL); 74 | } 75 | } 76 | 77 | std::vector rows; 78 | rows.resize(h); 79 | for(int y = 0; y < h; ++y) { 80 | rows[y] = img.data() + (stride * y); 81 | } 82 | png_set_rows(png, info, rows.data()); 83 | avif::util::StreamWriter out; 84 | png_set_write_fn(png, &out, Writer::png_write_callback_, nullptr); 85 | png_write_png(png, info, BitsPerComponent == 16 ? PNG_TRANSFORM_SWAP_ENDIAN : PNG_TRANSFORM_IDENTITY, nullptr); 86 | png_destroy_write_struct(&png, nullptr); 87 | auto result = avif::util::writeFile(filename_, out.buffer()); 88 | return result; 89 | } 90 | 91 | private: 92 | static void png_write_callback_(png_structp png_ptr, png_bytep data, png_size_t length); 93 | }; 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "../external/clipp/include/clipp.h" 19 | #include "img/png/Writer.hpp" 20 | #include "img/Conversion.hpp" 21 | 22 | namespace { 23 | 24 | bool endsWidh(std::string const& target, std::string const& suffix) { 25 | if(target.size() < suffix.size()) { 26 | return false; 27 | } 28 | return target.substr(target.size()-suffix.size()) == suffix; 29 | } 30 | 31 | std::string basename(std::string const& path) { 32 | auto pos = path.find_last_of('/'); 33 | if(pos == std::string::npos) { 34 | return path; 35 | } 36 | return path.substr(pos+1); 37 | } 38 | 39 | void nop_free_callback(const uint8_t *buf, void *cookie) { 40 | } 41 | 42 | void log_callback(void *cookie, const char *format, va_list ap) { 43 | auto* const log = static_cast(cookie); 44 | auto const len = vsnprintf(nullptr, 0, format, ap); 45 | std::string buff; 46 | buff.resize(len); 47 | vsnprintf(buff.data(), len, format, ap); 48 | log->info("[dav1d] {}", buff); 49 | } 50 | 51 | template 52 | std::optional findBox(avif::FileBox const& fileBox, uint32_t itemID) { 53 | for(auto const& assoc : fileBox.metaBox.itemPropertiesBox.associations){ 54 | for(auto const& item : assoc.items) { 55 | if(item.itemID != itemID) { 56 | continue; 57 | } 58 | for(auto const& entry : item.entries) { 59 | if(entry.propertyIndex == 0) { 60 | continue; 61 | } 62 | auto& prop = fileBox.metaBox.itemPropertiesBox.propertyContainers.properties.at(entry.propertyIndex - 1); 63 | if(std::holds_alternative(prop)){ 64 | return std::get(prop); 65 | } 66 | } 67 | } 68 | } 69 | return std::optional(); 70 | } 71 | 72 | avif::img::ColorProfile calcColorProfile(avif::FileBox const& fileBox, uint32_t const itemID, Dav1dPicture const& pic) { 73 | avif::img::ColorProfile prof = {}; 74 | namespace query = avif::util::query; 75 | std::optional const colr = query::findProperty(fileBox, itemID); 76 | if(colr.has_value()) { 77 | auto profile = colr.value().profile; 78 | if(std::holds_alternative(profile)) { 79 | prof.iccProfile = avif::img::ICCProfile(std::get(profile).payload); 80 | // FIXME(ledyba-z): gcc8 does not support this syntax. 81 | // return { 82 | // .iccProfile = avif::img::ICCProfile(std::get(profile).payload), 83 | // }; 84 | }else if(std::holds_alternative(profile)) { 85 | prof.iccProfile = avif::img::ICCProfile(std::get(profile).payload); 86 | // FIXME(ledyba-z): gcc8 does not support this syntax. 87 | // return { 88 | // .iccProfile = avif::img::ICCProfile(std::get(profile).payload), 89 | // }; 90 | }else if(std::holds_alternative(profile)) { 91 | prof.cicp = std::get(profile); 92 | // FIXME(ledyba-z): gcc8 does not support this syntax. 93 | // return { 94 | // .cicp = std::get(profile), 95 | // }; 96 | } 97 | } 98 | if(!prof.cicp.has_value()) { 99 | prof.cicp = std::make_optional(); 100 | prof.cicp->colourPrimaries = static_cast(pic.seq_hdr->pri); 101 | prof.cicp->transferCharacteristics = static_cast(pic.seq_hdr->trc); 102 | prof.cicp->matrixCoefficients = static_cast(pic.seq_hdr->mtrx); 103 | prof.cicp->fullRangeFlag = pic.seq_hdr->color_range == 1; 104 | // FIXME(ledyba-z): gcc8 does not support this syntax. 105 | // return { 106 | // .cicp = std::make_optional({ 107 | // .colourPrimaries = static_cast(pic.seq_hdr->pri), 108 | // .transferCharacteristics = static_cast(pic.seq_hdr->trc), 109 | // .matrixCoefficients = static_cast(pic.seq_hdr->mtrx), 110 | // .fullRangeFlag = pic.seq_hdr->color_range == 1, 111 | // }), 112 | // }; 113 | } 114 | return prof; 115 | } 116 | 117 | template 118 | avif::img::Image applyTransform(avif::img::Image img, avif::FileBox const& fileBox) { 119 | uint32_t itemID = 1; 120 | if(fileBox.metaBox.primaryItemBox.has_value()) { 121 | itemID = fileBox.metaBox.primaryItemBox.value().itemID; 122 | } 123 | std::optional clap = findBox(fileBox, itemID); 124 | std::optional irot = findBox(fileBox, itemID); 125 | std::optional imir = findBox(fileBox, itemID); 126 | if(!clap.has_value() && !irot.has_value() && !imir.has_value()) { 127 | return img; 128 | } 129 | // ISO/IEC 23000-22:2019(E) 130 | // p.16 131 | // These properties, if used, shall be indicated to be applied in the following order: 132 | // clean aperture first, 133 | // then rotation, 134 | // then mirror. 135 | if(clap.has_value()) { 136 | img = avif::img::crop(img, clap.value()); 137 | } 138 | if(irot.has_value()) { 139 | img = avif::img::rotate(img, irot.value().angle); 140 | } 141 | if(imir.has_value()) { 142 | img = avif::img::flip(img, imir.value().axis); 143 | } 144 | return img; 145 | } 146 | 147 | std::chrono::milliseconds::rep decodeImageAt( 148 | avif::util::Logger& log, 149 | std::shared_ptr const& res, 150 | uint32_t const itemID, Dav1dContext* ctx, 151 | Dav1dPicture& pic 152 | ) { 153 | Dav1dData data = { nullptr }; 154 | auto const buffBegin = res->buffer().data(); 155 | avif::FileBox const& fileBox = res->fileBox(); 156 | size_t const baseOffset = fileBox.metaBox.itemLocationBox.items.at(itemID - 1).baseOffset; 157 | size_t const extentOffset = fileBox.metaBox.itemLocationBox.items.at(itemID - 1).extents[0].extentOffset; 158 | size_t const extentLength = fileBox.metaBox.itemLocationBox.items.at(itemID - 1).extents[0].extentLength; 159 | auto const imgBegin = std::next(buffBegin, baseOffset + extentOffset); 160 | auto const imgEnd = std::next(imgBegin, extentLength); 161 | { 162 | auto start = std::chrono::steady_clock::now(); 163 | 164 | dav1d_data_wrap(&data, imgBegin, std::distance(imgBegin, imgEnd), nop_free_callback, nullptr); 165 | int err = dav1d_send_data(ctx, &data); 166 | 167 | if(err < 0) { 168 | log.fatal( "Failed to send data to dav1d: {}\n", err); 169 | } 170 | 171 | err = dav1d_get_picture(ctx, &pic); 172 | if (err < 0) { 173 | log.fatal("Failed to decode dav1d: {}\n", err); 174 | } 175 | auto finish = std::chrono::steady_clock::now(); 176 | return std::chrono::duration_cast(finish-start).count(); 177 | } 178 | } 179 | 180 | void saveImage( 181 | avif::util::Logger& log, 182 | std::string const& dstPath, 183 | avif::FileBox const& fileBox, 184 | Dav1dPicture& primary, 185 | avif::img::ColorProfile const& primaryProfile, 186 | std::optional> alpha 187 | ) { 188 | if(!endsWidh(dstPath, ".png")) { 189 | log.fatal("Please give png file for output: {}", dstPath); 190 | } 191 | 192 | std::optional writeResult; 193 | std::variant, avif::img::Image<16>> encoded = img::createImage(primary, primaryProfile, alpha); 194 | if(std::holds_alternative>(encoded)) { 195 | auto& img = std::get>(encoded); 196 | img = applyTransform(std::move(img), fileBox); 197 | img.colorProfile() = primaryProfile; 198 | writeResult = img::png::Writer(log, dstPath).write(img); 199 | } else { 200 | auto& img = std::get>(encoded); 201 | img = applyTransform(std::move(img), fileBox); 202 | img.colorProfile() = primaryProfile; 203 | writeResult = img::png::Writer(log, dstPath).write(img); 204 | } 205 | if(writeResult.has_value()) { 206 | log.fatal("Failed to write PNG: {}", writeResult.value()); 207 | } 208 | } 209 | 210 | } 211 | 212 | namespace internal { 213 | int main(int argc, char** argv); 214 | } 215 | 216 | int main(int argc, char** argv) { 217 | try { 218 | return internal::main(argc, argv); 219 | } catch (std::exception& err) { 220 | fprintf(stderr, "Fatal Error: %s\n", err.what()); 221 | fflush(stderr); 222 | return -1; 223 | } 224 | } 225 | 226 | int internal::main(int argc, char** argv) { 227 | avif::util::FileLogger log(stdout, stderr, avif::util::Logger::DEBUG); 228 | 229 | log.info("davif"); 230 | log.info(" - dav1d ver: {}", dav1d_version()); 231 | log.info(" - libpng ver: {}", img::png::Writer::version()); 232 | 233 | // Init dav1d 234 | Dav1dSettings settings = {}; 235 | dav1d_default_settings(&settings); 236 | // NOTE(ledyba-z): 237 | // If > 1, dav1d tends to buffer frames(?). See libavif 238 | settings.max_frame_delay = 1; 239 | settings.logger.cookie = &log; 240 | settings.logger.callback = log_callback; 241 | settings.n_threads = static_cast(std::thread::hardware_concurrency()); 242 | 243 | std::string inputFilename = {}; 244 | std::string outputFilename = {}; 245 | std::optional outputAlphaFilename = {}; 246 | std::optional outputDepthFilename = {}; 247 | bool showHelp = false; 248 | { 249 | using namespace clipp; 250 | auto convertFlags = ( 251 | required("-i", "--input") & value("input.avif", inputFilename), 252 | required("-o", "--output") & value("output.png", outputFilename), 253 | option("--extract-alpha") & value("output-alpha.png").call([&](std::string const& path){ outputAlphaFilename = path; }), 254 | option("--extract-depth") & value("output-depth.png").call([&](std::string const& path){ outputDepthFilename = path; }), 255 | option("--threads") & integer("Num of threads to use", settings.n_threads) 256 | ); 257 | auto supportFlags = ( 258 | option("-h", "--help").doc("Show help and exit.").set(showHelp, true) 259 | ); 260 | auto cli = (convertFlags | supportFlags); 261 | if(parse(argc, argv, cli).any_error()) { 262 | std::cerr << make_man_page(cli, basename(std::string(argv[0]))); 263 | return -1; 264 | } 265 | if(showHelp) { 266 | std::cerr << make_man_page(cli, basename(std::string(argv[0]))); 267 | return 0; 268 | } 269 | if(inputFilename == outputFilename) { 270 | std::cerr << "Input and output can't be the same file!" << std::endl; 271 | return -2; 272 | } 273 | } 274 | 275 | Dav1dContext* ctx = nullptr; 276 | 277 | if(int err = dav1d_open(&ctx, &settings); err != 0) { 278 | log.fatal("Failed to open dav1d: {}\n", err); 279 | } 280 | 281 | // Read file. 282 | std::variant, std::string> avif_data = avif::util::readFile(inputFilename); 283 | if(std::holds_alternative(avif_data)){ 284 | log.fatal("Failed to open input: {}\n", std::get<1>(avif_data)); 285 | } 286 | 287 | // parse ISOBMFF 288 | avif::Parser parser(log, std::move(std::get<0>(avif_data))); 289 | std::shared_ptr res = parser.parse(); 290 | if (!res->ok()) { 291 | log.fatal("Failed to parse {} as avif: {}\n", inputFilename, res->error()); 292 | } 293 | 294 | log.info("Decoding: {} -> {}", inputFilename, outputFilename); 295 | // start decoding 296 | avif::FileBox const& fileBox = res->fileBox(); 297 | Dav1dPicture primaryImg = {}; 298 | std::optional alphaImg = {}; 299 | namespace query = avif::util::query; 300 | uint32_t const primaryImageID = query::findPrimaryItemID(fileBox).value_or(1); 301 | { // primary image 302 | unsigned int elapsed = decodeImageAt(log, res, primaryImageID, ctx, primaryImg); 303 | log.info(" Decoded: {} -> {} in {} [ms]", inputFilename, outputFilename, elapsed); 304 | } 305 | auto primaryItemID = query::findPrimaryItemID(fileBox).value_or(1); 306 | avif::img::ColorProfile primaryProfile = calcColorProfile(fileBox, primaryItemID, primaryImg); 307 | avif::img::ColorProfile alphaProfile = {}; 308 | 309 | { // alpha image 310 | std::optional alphaID = query::findAuxItemID(fileBox, primaryImageID, avif::kAlphaAuxType()); 311 | if(alphaID.has_value()) { 312 | alphaImg = Dav1dPicture{}; 313 | unsigned int elapsed = decodeImageAt(log, res, alphaID.value(), ctx, alphaImg.value()); 314 | log.info(" Decoded: {} -> {} in {} [ms] (Alpha image)", inputFilename, outputFilename, elapsed); 315 | if(alphaImg.value().p.w != primaryImg.p.w || alphaImg.value().p.h != primaryImg.p.h) { 316 | // TODO(ledyba-z): It is okay to alpha image and primary image are different sizes. 317 | // see: https://github.com/AOMediaCodec/av1-avif/issues/68 318 | log.fatal("Currently, alpha image whose size ({} x {}) does not match to primary image ({} x {}) is not supported.", 319 | alphaImg.value().p.w, alphaImg.value().p.h, primaryImg.p.w, primaryImg.p.h); 320 | } 321 | if(outputAlphaFilename.has_value()) { 322 | alphaProfile = calcColorProfile(fileBox, alphaID.value(), alphaImg.value()); 323 | saveImage(log, outputAlphaFilename.value(), fileBox, alphaImg.value(), alphaProfile, std::optional>()); 324 | log.info(" Extracted: {} -> {} (Alpha image)", inputFilename, outputAlphaFilename.value()); 325 | } 326 | } else { 327 | if(outputAlphaFilename.has_value()) { 328 | log.fatal("{} does not have alpha plane.", inputFilename); 329 | } 330 | } 331 | } 332 | { // depth image 333 | std::optional depthID = query::findAuxItemID(fileBox, primaryImageID, avif::kDepthAuxType()); 334 | if(depthID.has_value()) { 335 | Dav1dPicture depthImg = {}; 336 | unsigned int elapsed = decodeImageAt(log, res, depthID.value(), ctx, depthImg); 337 | log.info(" Decoded: {} in {} [ms] (Depth image)", inputFilename, elapsed); 338 | if(depthImg.p.w != primaryImg.p.w || depthImg.p.h != primaryImg.p.h) { 339 | // TODO(ledyba-z): Can alpha image and primary image be different size? 340 | // see: https://github.com/AOMediaCodec/av1-avif/issues/68 341 | log.fatal("Alpha size ({} x {}) does not match to primary image({} x {}).", 342 | depthImg.p.w, depthImg.p.h, primaryImg.p.w, primaryImg.p.h); 343 | } 344 | if(outputDepthFilename.has_value()) { 345 | auto depthProfile = calcColorProfile(fileBox, depthID.value(), depthImg); 346 | saveImage(log, outputDepthFilename.value(), fileBox, depthImg, depthProfile, std::optional>()); 347 | log.info(" Extracted: {} -> {} (Depth image)", inputFilename, outputDepthFilename.value()); 348 | } 349 | }else{ 350 | if(outputDepthFilename.has_value()) { 351 | log.fatal("{} does not have depth plane.", inputFilename); 352 | } 353 | } 354 | } 355 | // Write to file. 356 | if(alphaImg.has_value()) { 357 | std::optional> alpha = std::make_optional(std::tuple(alphaImg.value(), alphaProfile)); 358 | saveImage(log, outputFilename, fileBox, primaryImg, primaryProfile, alpha); 359 | } else { 360 | saveImage(log, outputFilename, fileBox, primaryImg, primaryProfile, std::optional>()); 361 | } 362 | 363 | dav1d_picture_unref(&primaryImg); 364 | if(alphaImg.has_value()) { 365 | dav1d_picture_unref(&alphaImg.value()); 366 | } 367 | dav1d_close(&ctx); 368 | return 0; 369 | } 370 | --------------------------------------------------------------------------------