[
  {
    "path": ".dockerignore",
    "content": "build\n"
  },
  {
    "path": ".gitattributes",
    "content": "#sources\n*.c text\n*.cc text\n*.cxx text\n*.cpp text\n*.c++ text\n*.hpp text\n*.h text\n*.h++ text\n*.hh text\n\n# Compiled Object files\n*.slo binary\n*.lo binary\n*.o binary\n*.obj binary\n\n\n# Precompiled Headers\n*.gch binary\n*.pch binary\n\n\n# Compiled Dynamic libraries\n*.so binary\n*.dylib binary\n*.dll binary\n\n\n# Compiled Static libraries\n*.lai binary\n*.la binary\n*.a binary\n*.lib binary\n\n\n# Executables\n*.exe binary\n*.out binary\n*.app binary"
  },
  {
    "path": ".github/workflows/codeql.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL Analysis\"\n\non:\n  push:\n    branches: [ \"main\" ]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ \"main\" ]\n  schedule:\n    - cron: '40 9 * * 0'\n\nenv:\n  # Path to the CMake build directory.\n  build: '${{ github.workspace }}/build'\n  \njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'cpp' ]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]\n        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v3\n      \n    - name: Setup VCPKG\n      uses: friendlyanon/setup-vcpkg@v1\n      with: { committish: 63aa65e65b9d2c08772ea15d25fb8fdb0d32e557 }\n\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v2\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n\n        # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs\n        # queries: security-extended,security-and-quality\n\n\n    # Autobuild attempts to build any compiled languages  (C/C++, C#, Go, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    #- name: Autobuild\n    #uses: github/codeql-action/autobuild@v2\n      \n    - name: Configure CMake\n      run: cmake -B ${{ env.build }} --preset linux-x64-release\n        \n    # Build is not required for MSVC Code Analysis and will be used for Codecov\n    - name: Build CMake\n      run: cmake --build ${{ env.build }} --preset linux-x64-release\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun\n\n    #   If the Autobuild fails above, remove it and uncomment the following three lines.\n    #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.\n\n    # - run: |\n    #   echo \"Run, Build Application using script\"\n    #   ./location_of_script_within_repo/buildscript.sh\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v2\n      with:\n        category: \"/language:${{matrix.language}}\"\n"
  },
  {
    "path": ".github/workflows/msvc.yml",
    "content": "# This workflow uses actions that are not certified by GitHub.\n# They are provided by a third-party and are governed by\n# separate terms of service, privacy policy, and support\n# documentation.\n#\n# Find more information at:\n# https://github.com/microsoft/msvc-code-analysis-action\n\nname: Microsoft C++ Code Analysis\n\non:\n  push:\n    branches: [\"main\"]\n  pull_request:\n    branches: [\"main\"]\n  schedule:\n    - cron: \"41 16 * * 1\"\n\nenv:\n  # Path to the CMake build directory.\n  build: \"${{ github.workspace }}/build\"\n\npermissions:\n  contents: read\n\njobs:\n  analyze:\n    permissions:\n      contents: read # for actions/checkout to fetch code\n      security-events: write # for github/codeql-action/upload-sarif to upload SARIF results\n      actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status\n    name: Analyze\n    runs-on: windows-latest\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n\n      - name: Setup VCPKG\n        uses: friendlyanon/setup-vcpkg@v1\n        with: { committish: 63aa65e65b9d2c08772ea15d25fb8fdb0d32e557 }\n\n      - name: Get SW\n        uses: egorpugin/sw-action@master\n\n      - name: SW setup and add to PATH\n        run: |\n          ./sw setup\n          echo \"D:\\a\\WolfEngine\\WolfEngine\" >> $env:GITHUB_PATH\n\n      - name: Setup OpenCppCoverage and add to PATh\n        id: setup_opencppcoverage\n        run: |\n          choco install OpenCppCoverage -y\n          echo \"C:\\Program Files\\OpenCppCoverage\" >> $env:GITHUB_PATH\n\n      - name: Configure CMake\n        run: cmake -DCMAKE_BUILD_TYPE=Debug -B ${{ env.build }} \n         \n\n      # Build is not required for MSVC Code Analysis and will be used for Codecov\n      - name: Build CMake\n        run: cmake --build ${{ env.build }}\n\n      - name: Run MSVC Code Analysis\n        uses: microsoft/msvc-code-analysis-action@04825f6d9e00f87422d6bf04e1a38b1f3ed60d99\n        # Provide a unique ID to access the sarif output path\n        id: run-analysis\n        with:\n          cmakeBuildDirectory: ${{ env.build }}\n          # Ruleset file that will determine what checks will be run\n          ruleset: NativeRecommendedRules.ruleset\n          ignoredTargetPaths: ${{ env.build }}/_deps/boost_chrono-src;${{ env.build }}/_deps/boost_context-src;${{ env.build }}/_deps/boost_coroutine-src;${{ env.build }}/_deps/boost_date_time-src;${{ env.build }}/_deps/boost_exception-src;${{ env.build }}/_deps/fmt-src;${{ env.build }}/_deps/boost_container-src;${{ env.build }}/_deps/opencv-src;${{ env.build }}/_deps/rapidjson-src;${{ env.build }}/_deps/tesseract-src\n\n      - name: Generate Codecov Report\n        id: generate_test_report\n        shell: cmd\n        run: OpenCppCoverage.exe --continue_after_cpp_exception --export_type cobertura:WolfCov.xml --sources %CD% --excluded_sources %CD%\\build\\_deps -- %CD%\\build\\wolf\\Debug\\wolf_tests.exe\n      - name: Upload Report to Codecov\n        uses: codecov/codecov-action@v2\n        with:\n          files: ./WolfCov.xml\n          fail_ci_if_error: true\n          functionalities: fix\n\n      # Upload SARIF file to GitHub Code Scanning Alerts\n      #- name: Upload SARIF to GitHub\n      #  uses: github/codeql-action/upload-sarif@v2\n      #  with:\n      #    sarif_file: ${{ steps.run-analysis.outputs.sarif }}\n\n      # Upload SARIF file as an Artifact to download and view\n      - name: Upload SARIF as an Artifact\n        uses: actions/upload-artifact@v3\n        with:\n          name: sarif-file\n          path: ${{ steps.run-analysis.outputs.sarif }}\n"
  },
  {
    "path": ".gitignore",
    "content": "*.log\n*.tlog\n*.wLog\n*.idb\n*.pdb\n*.ipch\n*.ilk\n*.recipe\n*.res\n*.enc\n*.vscode\n*.advixeproj\n*.advixeexp\n*.dflgadvixe\n*.infoadvixe\n*.DS_Store\n*.db\n*.db-shm\n*.db-wal\n*.opendb\n*.DS_Store\n*.pem\n\n/bin/*\n/build/*\n/coverage/*\n/install/*\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch\n*.pch\n\n\n# Fortran module files\n*.mod\n\n\n# Executables\n*.exe\n*.out\n*.app"
  },
  {
    "path": "CHANGE_LOG.md",
    "content": "# ToDos\n- Dynamic lod creator for lod sample\n- Forward+\n- DirectX 12\n- Realtime Raytracing\n- DEBUG, RELEASE, MinSizeRelease(does not have assimp and just use wscene files)\n\n# 2.1\nA major release, rewrite most of wolf.system with pure C\n - fixed some bugs\n - improved memory pool\n - executing python from c has been added\n\n# 2.0.0.0\nA major release, rewrite most of wolf.system with pure C\n - Build for Win64\n - Build for OSX\n - Build for iOS\n - Build for Android-armv7\n - Build for Linux64\n\n\n# 1.68.0.9 (2018-10-03)\nA minor release with many compatibility-breaking changes.\n\nNew features:\n- CMAKE added for building wolf for linux platform\n\n# 1.65.0.0 (2018-06-04)\nA minor release with many compatibility-breaking changes.\n\nNew features:\n- system::w_logger optimized and integrated with spdlog \n- framework::w_media_core optimized for streaming\n- gpu occlusion culling has been added\n\n\n# 1.63.1.0 (2018-04-19)\n\nA minor release with many compatibility-breaking changes.\n\nNew features:\n- Integrated with Vulkan SDK version 1.1.73.0\n- Integrated with VulkanMemoryAllocator for better gpu memory managment\n- The new coordinate system is Left handed Y-Up \n- The function \"contains\" have been added to wolf::system::w_bounding_sphere\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.22)\n\n# set the name of the projects\nproject(wolf)\nadd_subdirectory(wolf)\n"
  },
  {
    "path": "CMakePresets.json",
    "content": "{\n    \"version\": 3,\n    \"cmakeMinimumRequired\": {\n        \"major\": 3,\n        \"minor\": 20\n    },\n    \"configurePresets\": [\n        {\n            \"name\": \"base\",\n            \"hidden\": true,\n            \"description\": \"base project for other configurations.\",\n            \"binaryDir\": \"${sourceDir}/build/${presetName}\",\n            \"installDir\": \"${sourceDir}/install/${presetName}\",\n            \"generator\": \"Ninja\",\n            \"cacheVariables\": {\n                \"CMAKE_TOOLCHAIN_FILE\": \"$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\",\n                \"ARCH\": \"win64\"\n            }\n        },\n        {\n            \"name\": \"wasm32-unknown-emscripten-debug\",\n            \"displayName\": \"wasm32-unknown-emscripten\",\n            \"description\": \"Configure debug mode based on Emscripten\",\n            \"inherits\": \"base\",\n            \"cacheVariables\": {\n                \"CMAKE_TOOLCHAIN_FILE\": \"$env{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake\",\n                \"CMAKE_BUILD_TYPE\": \"Debug\"\n            }\n        },\n        {\n            \"name\": \"wasm32-unknown-emscripten-release\",\n            \"displayName\": \"Win x64 Release\",\n            \"description\": \"Configure release mode based on Emscripten\",\n            \"inherits\": \"wasm32-unknown-emscripten-debug\",\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Release\"\n            }\n        },\n        {\n            \"name\": \"win-x64-debug\",\n            \"displayName\": \"Win x64 Debug\",\n            \"description\": \"Sets windows platform and debug build type for x64 arch\",\n            \"inherits\": \"base\",\n            \"architecture\": {\n                \"value\": \"x64\",\n                \"strategy\": \"external\"\n            },\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Debug\"\n            },\n            \"condition\": {\n                \"type\": \"equals\",\n                \"lhs\": \"${hostSystemName}\",\n                \"rhs\": \"Windows\"\n            }\n        },\n        {\n            \"name\": \"win-x64-release\",\n            \"displayName\": \"Win x64 Release\",\n            \"description\": \"Sets windows platform and release build type for x64 arch\",\n            \"inherits\": \"win-x64-debug\",\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Release\"\n            }\n        },\n        {\n            \"name\": \"base-android\",\n            \"hidden\": true,\n            \"inherits\": \"base\",\n            \"environment\": {\n                \"ANDROID_NDK_HOME\": \"$env{NDK}\",\n                \"ANDROID_NDK\": \"$env{NDK}\",\n                \"ANDROID_NATIVE_API_LEVEL\": \"24\",\n                \"ANDROID_PLATFORM\": \"android-24\"\n            },\n            \"cacheVariables\": {\n                \"ANDROID\": true,\n                \"CMAKE_TOOLCHAIN_FILE\": \"$env{ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake\",\n                \"ANDROID_STL\": \"c++_shared\",\n                \"ANDROID_ABI\": \"arm64-v8a\",\n                \"CPU\": \"armv8\",\n                \"CMAKE_ANDROID_ARCH_ABI\": \"arm64-v8a\",\n                \"CMAKE_EXPORT_COMPILE_COMMANDS\": \"ON\",\n                \"CMAKE_SYSTEM_NAME\": \"Android\"\n            }\n        },\n        {\n            \"name\": \"android-arm64-debug\",\n            \"inherits\": \"base-android\",\n            \"displayName\": \"Android ARM64 v8a Debug\",\n            \"description\": \"Sets android platform and debug build type for arm64-v8a arch\",\n            \"architecture\": {\n                \"value\": \"arm64-v8a\",\n                \"strategy\": \"external\"\n            },\n            \"environment\": {\n                \"ANDROID_ABI\": \"arm64-v8a\",\n                \"CPU\": \"armv8\",\n                \"ARCH\": \"aarch64\",\n                \"CMAKE_ANDROID_ARCH_ABI\": \"arm64-v8a\",\n                \"CMAKE_BUILD_TYPE\": \"Debug\"\n            },\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Debug\"\n            }\n        },\n        {\n            \"name\": \"android-arm64-release\",\n            \"displayName\": \"Android ARM64 v8a Release\",\n            \"description\": \"Sets android platform and release build type for arm64-v8a arch\",\n            \"inherits\": \"android-arm64-debug\",\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Release\"\n            },\n            \"environment\": {\n                \"CMAKE_BUILD_TYPE\": \"Release\"\n            }\n        },\n        {\n            \"name\": \"android-arm-debug\",\n            \"inherits\": \"base-android\",\n            \"displayName\": \"Android ARM eabi v7a Debug\",\n            \"description\": \"Sets android platform and debug build type for armeabi-v7a arch\",\n            \"architecture\": {\n                \"value\": \"armeabi-v7a\",\n                \"strategy\": \"external\"\n            },\n            \"environment\": {\n                \"ANDROID_ABI\": \"armeabi-v7a\",\n                \"CPU\": \"arm\",\n                \"ARCH\": \"arm\",\n                \"CMAKE_ANDROID_ARCH_ABI\": \"armeabi-v7a\",\n                \"CMAKE_BUILD_TYPE\": \"Debug\"\n            },\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Debug\",\n                \"ANDROID_ABI\": \"armeabi-v7a\",\n                \"CMAKE_ANDROID_ARCH_ABI\": \"armeabi-v7a\",\n                \"ARCH\": \"arm\",\n                \"CPU\": \"arm\"\n            }\n        },\n        {\n            \"name\": \"android-arm-release\",\n            \"displayName\": \"Android ARM eabi v7a Release\",\n            \"description\": \"Sets android platform and release build type for armeabi-v7a arch\",\n            \"inherits\": \"android-arm-debug\",\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Release\"\n            },\n            \"environment\": {\n                \"CMAKE_BUILD_TYPE\": \"Release\"\n            }\n        },\n        {\n            \"name\": \"linux-x64-debug\",\n            \"displayName\": \"GCC x64 linux gnu debug\",\n            \"description\": \"Using compilers: C = /usr/bin/gcc, CXX = /usr/bin/g++\",\n            \"binaryDir\": \"${sourceDir}/build/${presetName}\",\n            \"cacheVariables\": {\n                \"CMAKE_INSTALL_PREFIX\": \"${sourceDir}/build/install/${presetName}\",\n                \"CMAKE_C_COMPILER\": \"gcc\",\n                \"CMAKE_CXX_COMPILER\": \"g++\",\n                \"CMAKE_BUILD_TYPE\": \"Debug\"\n            }\n        },\n        {\n            \"name\": \"linux-x64-release\",\n            \"displayName\": \"GCC x64 linux gnu release\",\n            \"inherits\": \"linux-x64-debug\",\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Release\"\n            }\n        }\n    ],\n    \"buildPresets\": [\n        {\n            \"name\": \"wasm32-unknown-emscripten-debug\",\n            \"displayName\": \"wasm32-unknown-emscripten-debug\",\n            \"description\": \"Build WebAssembly with Emscripten\",\n            \"configurePreset\": \"wasm32-unknown-emscripten-debug\"\n        },\n        {\n            \"name\": \"wasm32-unknown-emscripten-release\",\n            \"displayName\": \"wasm32-unknown-emscripten-release\",\n            \"description\": \"Build WebAssembly with Emscripten\",\n            \"configurePreset\": \"wasm32-unknown-emscripten-release\"\n        },\n        {\n            \"name\": \"win-x64-release\",\n            \"displayName\": \"Win x64 Release\",\n            \"description\": \"Sets windows platform and debug build type for x64 arch in release mode\",\n            \"configurePreset\": \"win-x64-release\"\n        },\n        {\n            \"name\": \"win-x64-debug\",\n            \"displayName\": \"Win x64 Debug\",\n            \"description\": \"Sets windows platform and debug build type for x64 arch in debug mode\",\n            \"configurePreset\": \"win-x64-debug\"\n        },\n        {\n            \"name\": \"android-arm64-debug\",\n            \"displayName\": \"Android ARM64 v8a Debug\",\n            \"description\": \"Build Android\",\n            \"configurePreset\": \"android-arm64-debug\"\n        },\n        {\n            \"name\": \"android-arm64-release\",\n            \"displayName\": \"Android ARM64 v8a Release\",\n            \"description\": \"Build Android\",\n            \"configurePreset\": \"android-arm64-release\"\n        },\n        {\n            \"name\": \"android-arm-debug\",\n            \"displayName\": \"Android ARM eabi v7a Debug\",\n            \"description\": \"Build Android\",\n            \"configurePreset\": \"android-arm-debug\"\n        },\n        {\n            \"name\": \"android-arm-release\",\n            \"displayName\": \"Android ARM eabi v7a Release\",\n            \"description\": \"Build Android\",\n            \"configurePreset\": \"android-arm-release\"\n        },\n        {\n            \"name\": \"linux-x64-debug\",\n            \"displayName\": \"Sets linux platform and debug build type for x64 arch in debug mode\",\n            \"description\": \"linux x64 Debug\",\n            \"configurePreset\": \"linux-x64-debug\"\n        },\n        {\n            \"name\": \"linux-x64-release\",\n            \"displayName\": \"Sets linux platform and release build type for x64 arch in release mode\",\n            \"description\": \"linux x64 Release\",\n            \"configurePreset\": \"linux-x64-release\"\n        },\n        {\n            \"name\": \"wasm\",\n            \"description\": \"\",\n            \"displayName\": \"\",\n            \"configurePreset\": \"wasm32-unknown-emscripten-debug\"\n        }\n    ],\n    \"testPresets\": [\n        {\n            \"name\": \"base-tests\",\n            \"hidden\": true,\n            \"output\": {\n                \"outputOnFailure\": true\n            }\n        },\n        {\n            \"name\": \"windows-tests\",\n            \"inherits\": \"base-tests\",\n            \"configurePreset\": \"win-x64-debug\"\n        }\n    ]\n}"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, caste, color, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\npooya{dot}eimandar{at}gmail{dot}com.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.1, available at\n[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].\n\nCommunity Impact Guidelines were inspired by\n[Mozilla's code of conduct enforcement ladder][Mozilla CoC].\n\nFor answers to common questions about this code of conduct, see the FAQ at\n[https://www.contributor-covenant.org/faq][FAQ]. Translations are available\nat [https://www.contributor-covenant.org/translations][translations].\n\n[homepage]: https://www.contributor-covenant.org\n[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html\n[Mozilla CoC]: https://github.com/mozilla/diversity\n[FAQ]: https://www.contributor-covenant.org/faq\n[translations]: https://www.contributor-covenant.org/translations\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# [Here is the Rust implementation of Wolf](https://github.com/WolfEngine/WolfEngine/tree/wolf-rs)\n\n### Wolf Engine [![Apache licensed](https://img.shields.io/badge/license-Apache-blue)](https://github.com/WolfEngine/Wolf.Engine/blob/main/LICENSE.md) [![codecov](https://codecov.io/github/WolfEngine/WolfEngine/branch/main/graph/badge.svg?token=AhoU9QV7eS)](https://codecov.io/github/WolfEngine/WolfEngine) [![CodeQL](https://github.com/WolfEngine/WolfEngine/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/WolfEngine/WolfEngine/actions/workflows/codeql.yml) [![Microsoft C++ Code Analysis](https://github.com/WolfEngine/WolfEngine/actions/workflows/msvc.yml/badge.svg?branch=main)](https://github.com/WolfEngine/WolfEngine/actions/workflows/msvc.yml)\n\n<img src=\"https://raw.githubusercontent.com/WolfEngine/WolfEngine/main/Logo.png\" width=\"256\" height=\"256\" alt=\"WolfEngine\"/>\n<p><b>Welcome to the Wolf Engine source code.</b></p> \n<p>The&nbsp;<b>Wolf Engine</b>&nbsp;is the next\ngeneration of&nbsp;<a href=\"https://github.com/PooyaEimandar/PersianEngine\">Persian Game Engine</a>&nbsp;which is a\ncross-platform open source game engine created by&nbsp;<a href=\"https://pooyaeimandar.github.io/\">Pooya Eimandar</a>.\nThe Wolf is a comprehensive set of C++ open source libraries for realtime rendering, realtime streaming and game developing, which is support <b>Lua</b> and <b>WASM</b> as an embedded scripting languages.</p>\n\n# Build\n- Prerequisites \n      - For windows, make sure install the latest Windows 11/10 SDK\n\t- [git](https://git-scm.com/downloads)\n\t- [CMake](https://cmake.org/download/)\n\t- [vcpkg](https://vcpkg.io/)\n\t- [Meson](https://github.com/mesonbuild/meson/releases)\n\t- [Ninja](https://ninja-build.org/). Alternatively, setup [Python3](https://www.python.org/downloads/) and use \"pip3 install ninja\"\n\t- [QT6](https://www.qt.io/download) for demos and examples\n\t- [NDK](https://developer.android.com/ndk/downloads) for android.\n\t\nthen make sure get the main branch \n`git clone https://github.com/WolfEngine/WolfEngine.git --branch main --depth 1`\n\n## CMakePresets\n\t\nTo list configure presets: `cmake . --list-presets`\nTo list build presets: `cmake --build --list-presets`\nTo install wolf: `cmake --install <build-dir> --prefix <prefix>`\n\nFor example for building wolf for android:\n```\ncmake . --preset android-arm64-release\ncmake --build --preset android-arm64-release\n```\n\nFor example for building wolf for windows:\n```\ncmake . --preset win-x64-release\ncmake --build --preset win-x64-release\ncmake --install C:/WolfEngine/build/win-x64-release --prefix C:/wolf\n```\n\n## Recent Sample\n<p>Dynamic LOD Generation using <a href=\"https://www.simplygon.com/\" target=\"_blank\">Simplygon</a></p>\n<img src=\"https://raw.githubusercontent.com/WolfEngine/WolfEngine/wolf-2/samples/03_advances/07_lod/doc/view.gif\" width=\"640\" height=\"360\" alt=\"Dynamic LOD Generation gif\"/>\n\n## Supported platforms\n\n| Not Supported | Planned | In Progress | Done |\n|:-----------:|:-----------:|:-----------:|:-----------:|\n| :x: | :memo: | :construction: | :white_check_mark: | \n\n### Supported platforms and APIs for render module\n\n| API | Windows | Linux | macOS | iOS | Android | Wasm |\n|:-----------:|:-----------:|:--------------------------:|:--------------:|:-------------:|:--------------:|:-------------:|\n| GPU | Vulkan/OpenGL ES :construction: | Vulkan/OpenGL ES :memo: | MoltenVK :memo: | MoltenVK :memo: | Vulkan/OpenGL ES :memo: | WebGL/WebGPU :memo: |\n\n### Supported platforms and APIs for media module\n\n| API | Windows | Linux | macOS | iOS | Android | Wasm |\n|:-----------:|:-----------:|:--------------------------:|:--------------:|:-------------:|:--------------:|:-------------:|\n| [Bitmap](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/media/test/ffmpeg.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :x: |\n| [FFmpeg](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/stream/test/ffmpeg_stream.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :x: |\n| [JPEG](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/media/test/ffmpeg.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :x: |\n| [OpenAL](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/media/test/openal.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :x: |\n| [PNG](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/media/test/ffmpeg.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :x: |\n| WebP | :memo: | :memo: | :memo: | :memo: | :memo: | :x: |\n\n### Supported platforms and APIs for stream module\n\n| API | Windows | Linux | macOS | iOS | Android | Wasm |\n|:-----------:|:-----------:|:--------------------------:|:--------------:|:-------------:|:--------------:|:-------------:|\n| gRPC | :memo: | :x: | :x: | :x: | :x: | :x: |\n| [Janus](https://github.com/WolfEngine/WolfEngine/tree/main/wolf_demo/wasm) | :construction: | :x: | :x: | :x: | :x: | :white_check_mark: |\n| [QUIC](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/stream/test/quic.hpp) | :white_check_mark: | :memo: | :memo: | :memo: | :memo: | :x: |\n| [RIST](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/stream/test/rist.hpp) | :white_check_mark: | :memo: | :memo: | :memo: | :white_check_mark: | :x: |\n| RTMP | :memo: | :x: | :x: | :x: | :x: | :x: |\n| [RTSP](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/stream/test/ffmpeg_stream.hpp) | :white_check_mark: | :memo: | :memo: | :memo: | :memo: | :x: |\n| [SRT](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/stream/test/ffmpeg_stream.hpp) | :white_check_mark: | :memo: | :memo: | :memo: | :memo: | :x: |\n| webRTC | :memo: | :memo: | :memo: | :memo: | :memo: | :memo: |\n| [WebSocket](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/ws.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :memo: |\n\n### Supported platforms and APIs for system module\n\n| API | Windows | Linux | macOS | iOS | Android | Wasm |\n|:-----------:|:-----------:|:--------------------------:|:--------------:|:-------------:|:--------------:|:-------------:|\n| [Coroutine](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/coroutine.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :x: | :x: | :x: |\n| [GameTime](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/gametime.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :white_check_mark: |\n| [Gamepad](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/gamepad.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :white_check_mark: |\n| [Virtual Gamepad](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/gamepad.hpp) | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |\n| [Log](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/log.hpp)  | :white_check_mark: | :white_check_mark: | :construction: | :construction: | :construction: | :construction: | \n| LuaJit  | :memo: | :memo: | :memo: | :memo: | :memo: | :x: |\n| [LZ4](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/compress.hpp)  | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :x: |\n| [LZMA](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/compress.hpp)  | :white_check_mark: | :white_check_mark: | :memo: | :x: | :x: | :x: |\n| OpenTelemetry  | :memo: | :memo: | :memo: | :x: | :x: | :x: |\n| RAFT  | :memo: | :memo: | :memo: | :memo: | :memo: | :memo: |\n| Screen Capture  | :memo: | :construction: | :construction: | :x: | :x: | :x: |\n| [Signal Slot](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/signal_slot.hpp)  | :white_check_mark: | :white_check_mark: | :construction: | :x: | :x: | :x: |\n| [Stacktrace](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/tests.cpp)  | :white_check_mark: | :white_check_mark: | :construction: | :construction: | :construction: | :x: |\n| Sycl  | :memo: | :memo: | :memo: | :x: | :x: | :x: |\n| [TCP](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/tcp.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :x: |\n| [Trace](https://github.com/WolfEngine/WolfEngine/blob/main/wolf/system/test/trace.hpp) | :white_check_mark: | :white_check_mark: | :memo: | :memo: | :memo: | :x: |\n| UDP | :construction: | :memo: | :memo: | :memo: | :memo: | :x: |\n| Wasm3  | :memo: | :memo: | :memo: | :memo: | :memo: | :memo: |\n\n## Projects using Wolf</h2>\n* [Wolf.Playout](https://www.youtube.com/watch?v=EZSdEjBvuGY), a playout automation software\n* [Falcon](https://youtu.be/ygpz35ddZ_4), a real time 3D monitoring system\n* [PlayPod](https://playpod.ir), the first cloud gaming platform launched in Middle East\n* [RivalArium](https://rivalarium.com), play and rival other users via our leagues and duels from any device, any location and let your skills generate income\n\n## [Youtube](https://www.youtube.com/c/WolfEngine)\n## [Twitter](https://www.twitter.com/Wolf_Engine)\n\nWolf Engine © 2014-2023 [Pooya Eimandar](https://www.linkedin.com/in/pooyaeimandar/)\n"
  },
  {
    "path": "TODO.md",
    "content": "- support android\n- support windows\n- support linux\n- support osx\n- support ios\n\n"
  },
  {
    "path": "coverage.bat",
    "content": "OpenCppCoverage.exe --continue_after_cpp_exception --export_type=html:%CD%\\coverage\\ --sources %CD% --excluded_sources %CD%\\build\\_deps -- %CD%\\build\\wolf\\Debug\\wolf_tests.exe"
  },
  {
    "path": "docker/Dockerfile",
    "content": "ARG UBUNTU_VERSION=\"22.04\"\nFROM ubuntu:${UBUNTU_VERSION}\n\nENV VCPKG_ROOT=/opt/vcpkg\nARG VCPKG_GITHUB_REPOSITORY=https://github.com/microsoft/vcpkg/archive/master.tar.gz\nARG VCPKG_COMPRESSED_FILE_NAME=vcpkg.tar.gz\n\nRUN set -eux \\\n\t&& export DEBIAN_FRONTEND=\"noninteractive\" \\\n\t&& apt-get update \\\n\t&& apt-get install --yes --no-install-recommends \\\n\t\tbuild-essential \\\n\t\tca-certificates \\\n\t\tcmake \\\n\t\tcpp \\\n\t\tcurl \\\n\t\tgit \\\n\t\tmake \\ls\n\t\tpkg-config \\\n\t\ttar \\\n\t\tunzip \\\n\t\twget \\\n\t\tzip\n\nWORKDIR  ${VCPKG_ROOT}\n\nRUN wget -qO ${VCPKG_COMPRESSED_FILE_NAME} ${VCPKG_GITHUB_REPOSITORY} \\\n\t&& tar xf ${VCPKG_COMPRESSED_FILE_NAME} --strip-components=1 \\\n\t&& rm ${VCPKG_COMPRESSED_FILE_NAME} \\\n\t&& /opt/vcpkg/bootstrap-vcpkg.sh \\\n\t&& ln -s /opt/vcpkg/vcpkg /usr/local/bin/vcpkg\n\nWORKDIR /workspace\n\nCOPY . .\n\nRUN cmake -B build --preset linux-x64-release\n\nRUN rm -rf ./*\n"
  },
  {
    "path": "docs/GCC.txt",
    "content": "cd /home/build\nGCC_VERSION=10.2.0\nwget https://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.gz\ntar xzvf gcc-${GCC_VERSION}.tar.gz\nmkdir obj.gcc-${GCC_VERSION}\ncd gcc-${GCC_VERSION}\n./contrib/download_prerequisites\ncd ../obj.gcc-${GCC_VERSION}\n#RedHat base\nsudo yum groupinstall \"Development Tools\"\n#Debian\nsudo apt-get install build-essential\n../gcc-${GCC_VERSION}/configure --disable-multilib --enable-languages=c,c++\nmake -j $(nproc)\nmake install\n"
  },
  {
    "path": "docs/ProblemSolutions.txt",
    "content": "-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\n--------------------  Problem\t-----------------------\t\t\t\t\t\t--------------------  Solution\t-----------------------\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\ninitializePlugin function could not be found in\t\t\t\t\t\t\t\tAdd following command to the Liker->command Line \nMaya plug-in\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"/export:initializePlugin /export:uninitializePlugin\"\n\t\t\t\t\t\t\t\t\t\n\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\nNo target architecture error at compile time\t\t\t\t\t\t\t\tuse #include <windows.h> instead of #include <WinDef.h>\n\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\n\nCopy relative content to the execution directory\t\t\t\t\t\t\t$(OutDir)/%(RelativeDir)/%(filename).cso for more info\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsee following link\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thttp://msdn.microsoft.com/en-us/library/ms164313.aspx\n\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\n\nDebug does not active, breakpoint disable\t\t\t\t\t\t\t\t\tProperties->Linker->debugging->GenerateDebugInfo->yes\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tProperties->Linker->debugging->DebuggingAssembly->yes\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tProperties->C/C++->Code Generation->Multi-threaded Debug DLL (/MDd)\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\nCould not find entry point \t\t\t\t\t\t\t\t\t\t\t\t\tFirst right click on \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSolution->Properties->Configuration Manager\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tset the x64\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tThen check dllMain or main function\t \n\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\nerror MSB6006: \"icl.exe\" exited with code 4\t\t\t\t\t\t\t\t\tswitch from intel c++ to microsoft visual c++ to check other errors, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talsoCheck precompiled headers\n\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\nerror LNK2019: unresolved external symbol __imp___CrtDbgReportW\t\t\t\tRemove _DEBUG from preprocessor or somwhere in your code\nreferenced in function, when you add std::map or std::vector\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\nCan link constructor or destructor ot method of a class\t\t\t\t\t\tmake sure add API(see W_Object.h) before declaration of method in class\nfrom DLL\t\t\t\t\t\n\n\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\neglGetPlatformDisplayEXT does not generate display device\t\t\t\t\tmake sure copy libGLESv2.dll, libEGL.dll & d3dcompiler_47.dll in bin folder\nin Angle project             \n\n-------------------------------------------------------\t\t\t\t\t\t-------------------------------------------------------\nError\tMSB6006\t\"fxc.exe\" exited with code 1.\t\t\t\t\t\t\t\tcheck all *.hlsl codes and shader type in Properties->HLSL Compiler->General in your project                                             \n\n\n\n\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\n\n\n \t\t\t\t\t\t    \t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \n\n\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\n\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\n\n\n\n\n"
  },
  {
    "path": "docs/git-commands.txt",
    "content": "//subtrees\n\ngit config commit.gpgsign false\ngit fetch git@github.com:g-truc/glm.git master\ngit subtree add --prefix=engine/dependencies/glm-master/ --squash git@github.com:g-truc/glm.git master\ngit subtree pull --prefix=engine/dependencies/glm-master/ --squash git@github.com:g-truc/glm.git master\n\ngit fetch git@github.com:dwd/rapidxml.git master\ngit subtree add --prefix=engine/dependencies/rapidxml-master/ --squash git@github.com:dwd/rapidxml.git master\ngit subtree pull --prefix=engine/dependencies/rapidxml-master/ --squash git@github.com:dwd/rapidxml.git master\n\ngit fetch git@github.com:miloyip/rapidjson.git master\ngit subtree add --prefix=engine/dependencies/rapidjson-master/ --squash git@github.com:miloyip/rapidjson.git master\ngit subtree pull --prefix=engine/dependencies/rapidjson-master/ --squash git@github.com:miloyip/rapidjson.git master\n"
  },
  {
    "path": "docs/glslValidator.txt",
    "content": "./glslangValidator.exe -V -t -o ~path/to/out.spv ~/path/to/in.vert"
  },
  {
    "path": "docs/glslValidator_MoltenVK.txt",
    "content": "cd /Users/pooyaeimandar/Documents/github/WolfSource/Wolf.Engine/engine/dependencies/vulkan/Mac/Molten/MoltenShaderConverter/Tools/\n\n./MoltenShaderConverter -gi /Users/pooyaeimandar/Documents/github/WolfSource/Wolf.Engine/samples/02_basics/02_shader/src/content/shaders/shader.frag -t f -so /Users/pooyaeimandar/Documents/github/WolfSource/Wolf.Engine/samples/02_basics/02_shader/src/content/shaders/shader.frag.spv\n\n\n./MoltenShaderConverter -gi /Users/pooyaeimandar/Documents/github/WolfSource/Wolf.Engine/samples/02_basics/02_shader/src/content/shaders/shader.vert -t v -so /Users/pooyaeimandar/Documents/github/WolfSource/Wolf.Engine/samples/02_basics/02_shader/src/content/shaders/shader.vert.spv"
  },
  {
    "path": "docs/quic.md",
    "content": "# Wolf QUIC\n\nWolf provides quic protocol as a submodule under stream module. Current implementation is mostly a C++ wrapper over msquic which is written in C, along with a few helpers to simplify and help with common usages such as client/server.\n\nThere are one to one C++ wrapper types for msquic types. including enums and flags, core data types to hold information, and handle types. public methods and member variables are also kind of one to one with similar name, sometimes with a little modification to ease the use.\n\nHandle instances which are async and have callbacks (connection and stream) have internal refcounting, and when running an instance of them will be managed internally and won't be destroyed/closed until stopped or are shut down. this allows, for example, one to start running an instance of connection in a listener callback and not to worry of managing its lifetime. and if an instance wasn't started, once its out of scope, it will automatically be closed.\n\nDue to the way msquic was designed, the parentship of instances like stream by connection and connection/listener by registration must be handled by user of this library. for example: when a connection is closed, the stream will automatically shut down and user must ensure that stream instances held by them will no longer be accessed or avilable.\n\nSo make sure dependent handles **DO NOT** outlive their dependencies. hopefully in the future this will be managed internally.\n\nTo understand these dependencies please refer to `API` overview documenetation of msquic: https://github.com/microsoft/msquic/blob/main/docs/API.md\n\n## Base Data Types\n\nMsquic enums/flags have an equivalent enum classes to be used. for bit flags, `w_flags` is used to handle bitwise operations.\n\nThe header `stream/quic/datatypes/common_flags.hpp` defines common enum flags used throughout the project.\n\nFor alpn name, since it is not forced to be a string, there is `w_alpn_view` in `stream/quic/datatypes/w_alpn.hpp` which represents an alpn name and is simply an alias to `std::span<uint8_t>`. it comes with `as_alpn_view` helper method to create view from string views and c strings.\n\nHere is a list of C++ wrapper types and their corresponding msquic types:\n - `w_address` represents `QUIC_ADDRESS`.\n\n - `w_status` and `w_status_code` represent `QUIC_STATUS`. the first is for holding a status code and checking whether it succeeded or failed, and the latter is an enum representing different status codes defined by msquic.\n\n - `w_settings` represents `QUIC_SETTINGS`, having each field as an `std::optional` so it can be easily aggregate initialized with specific field. e.g. `w_settings { .idle_timeout_ms = 2000 }`.\n\n - `w_credential_config` represents `QUIC_CREDENTIAL_CONFIG`, and for convenience there are `w_certificate_<something>` alongside it to represent `QUIC_CERTIFICATE_<SOMETHING>` and be used with ease to construct a credential config with any certificate without worrying about value semantics.\n\n - `w_registration_config` represents `QUIC_REGISTRATION_CONFIG`, and its fields are accessible through set/get methods.\n\n - `w_new_connection_info` represents `QUIC_NEW_CONNECTION_INFO`, and its fields are readonly, accessible through const methods with same name.\n\n## Events\n\nJust as msquic uses callbacks with event as a parameter, those event types are wrapped and represented by classes.\n\nEvent types are similar to `std::variant`, and to access the underlying event value, it must be visited with an overload set. wolf library provides `system/w_overloaded` to overload lambdas to ease this.\n\nAll event types also have a `name` method to get the underlying type's name string.\n\nThere are no fields, but wrapper classes for each specific event, named as `w_<handle-name>_event_<event-name>`, e.g. `w_listener_event_new_connection`. these event classes hold the underlying data, and provide getter and helper methods to interact with them.\n\nEvents can not be created, copied, or moved. their lifetime is solely in hands of wolf library that passes them to callback/visitor.\n\n - `w_listener_event` represents `QUIC_LISTENER_EVENT`. in `w_listener_event_new_connection` there are accept/reject methods which shouldn't be called more than once or over each other, and if neither is called then the connection will be rejected.\n\n - `w_conection_event` represents `QUIC_CONNEcTION_EVENT`, and just like `w_listener_event_new_connection` there is `w_connection_event_peer_stream_started` that has accept/reject methods and by default rejects if neither is called.\n\n - `w_stream_event` represents `QUIC_STREAM_EVENT`.\n\n## Handles\n\nThe handles in msquic all have the type of `HQUIC`. but here are the common concepts and kinds of handles provided by msquic which have their own api, and wolf has wrapper for them:\n\n - Registration: `w_registration` which on destruction waits on its children to be closed.\n\n - Configuration: `w_configuration`.\n\n - Listener: `w_listener` which starts and works async with callback, but it will shutdown when its last instance goes out of scope.\n\n - Connection: `w_connection` which starts and works async with callback, and will be kept alive/running even if there are no instances of it kept by user. thus user can easily accept/open a new connection and not have to worry about its lifetime.\n\n - Stream: `w_stream` which starts and works async with callbacks, and will be kept alive/running even if there are no instances of it kept by user. thus user can easily accept/open a new stream and not have to worry about its lifetime.\n\nHandles can not be constructed and are created by (commonly named `open`) factory static methods, using boost::leaf for error report and handling.\n\nCallbacks passed to create/set_callback of handle can be any callable and its storage will be internally managed.\n\nWolf doesn't provide the `context` pointer concept of msquic to user of this library, so instead use lambda captures or other C++-based alternatives.\n\n## For Developer/Contributor (Internals)\n\nMsquic's api table is created only once and is provided by singleton-style factory method `internal::w_msquic_api::api`.\n\nAs a C wrapper library there are many scenarios which one C function/type requires another C instance, and for this reason `internal::w_raw_access` pattern is used. classes which wrap a raw/C type declare that as `freind` class and provide desired private api so in any other part in the library if raw access is required, it can be gained via `internal::w_raw_access` can be used and these two types/methods need not to know of each other (necessary for generics). saving us tons of forward declarations and maintenance bookkeepings.\n\nHandles are kept lightweight, only have the `HQUIC` pointer as data member, and all of their required shared data is allocated on heap (the type `context_bundle`) and saved in the handle's context. so the context pointer must never change/written and should be always read for concurrency safety.\n"
  },
  {
    "path": "manifest.manifest",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\" xmlns:asmv3=\"urn:schemas-microsoft-com:asm.v3\">\n  <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n    <security>\n      <requestedPrivileges>\n        <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"></requestedExecutionLevel>\n      </requestedPrivileges>\n    </security>\n  </trustInfo>\n  <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n    <application>\n\t    <!-- Windows 10 --> \n        <supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n        <!-- Windows 8.1 -->\n        <supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\"/>\n        <!-- Windows Vista -->\n        <supportedOS Id=\"{e2011457-1546-43c5-a5fe-008deee3d3f0}\"/> \n        <!-- Windows 7 -->\n        <supportedOS Id=\"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}\"/>\n        <!-- Windows 8 -->\n        <supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\"/>\n    </application>\n  </compatibility>\n</assembly>"
  },
  {
    "path": "wolf/.clang-format",
    "content": "# http://clang.llvm.org/docs/ClangFormatStyleOptions.html\nBasedOnStyle: Google\n# This defaults to 'Auto'. Explicitly set it for a while, so that\n# 'vector<vector<int> >' in existing files gets formatted to\n# 'vector<vector<int>>'. ('Auto' means that clang-format will only use\n# 'int>>' if the file already contains at least one such instance.)\nStandard: Cpp11\nSortIncludes: true\nAllowShortIfStatementsOnASingleLine: false\nAllowShortLoopsOnASingleLine: false\nBreakStringLiterals: false\nDerivePointerAlignment: true\nPointerAlignment: Left\nColumnLimit: 100\nForEachMacros: ['list_for_every_entry','list_for_every_entry_safe']\nIncludeBlocks: Regroup\nIncludeCategories:\n  # This specific header must come last in kernel source files.  Its\n  # matching rule must come first so the lower-priority rules don't match.\n  - Regex:           '^<ktl/enforce\\.h>'\n    Priority:        1000\n  # C Header: <foo.h>, <net/foo.h>, etc\n  - Regex:           '^(<((zircon/|lib/|fuchsia/|arpa/|net/|netinet/|sys/|fidl/)[a-zA-Z0-9_/\\.-]+\\.h|[a-zA-Z0-9_-]+\\.h)>)'\n    Priority:        1\n  # Cpp Header: <foo> and <experimental/foo>\n  - Regex:           '^(<(experimental/)*[a-zA-Z0-9_-]+>)'\n    Priority:        2\n  # Libraries: <foo/bar.h>\n  - Regex:           '^(<[a-zA-Z0-9_/-]+\\.h>)'\n    Priority:        3\n  # Local headers: \"foo/bar.h\"\n  - Regex:           '^(\"[.a-zA-Z0-9_/-]+\\.h\")'\n    Priority:        4"
  },
  {
    "path": "wolf/.clang-tidy",
    "content": "---\nChecks: >\n  -*,\n  bugprone-*,\n  clang-diagnostic-*,\n  -clang-diagnostic-unused-command-line-argument,\n  google-*,\n  -google-runtime-references,\n  misc-*,\n  -misc-noexcept*,\n  -misc-unused-parameters,\n  -misc-const-correctness,\n  modernize-*,\n  -modernize-avoid-c-arrays,\n  -modernize-deprecated-headers,\n  -modernize-raw-string-literal,\n  -modernize-return-braced-init-list,\n  -modernize-use-auto,\n  -modernize-use-equals-delete,\n  -modernize-use-nodiscard,\n  -modernize-use-trailing-return-type,\n  performance-*,\n  readability-*,\n  -readability-function-cognitive-complexity,\n  -readability-identifier-length,\n  -readability-implicit-bool-conversion,\n  -readability-isolate-declaration,\n  -readability-magic-numbers,\n  -readability-qualified-auto,\n  -readability-uppercase-literal-suffix,\n  -readability-identifier-length,\n  -readability-named-parameter,\nWarningsAsErrors: false\nAnalyzeTemporaryDtors: false\nFormatStyle:     file\nCheckOptions:\n  - key:             bugprone-signed-char-misuse.CharTypdefsToIgnore\n    value:           'int8_t'\n  - key:             bugprone-assert-side-effect.AssertMacros\n    value:           'FXL_DCHECK'\n  - key:             google-readability-braces-around-statements.ShortStatementLines\n    value:           '2'\n  - key:             google-readability-function-size.StatementThreshold\n    value:           '800'\n  - key:             google-readability-namespace-comments.ShortNamespaceLines\n    value:           '10'\n  - key:             google-readability-namespace-comments.SpacesBeforeComments\n    value:           '2'\n  - key:             misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic\n    value:           '1'\n  - key:             modernize-loop-convert.MaxCopySize\n    value:           '16'\n  - key:             modernize-loop-convert.MinConfidence\n    value:           reasonable\n  - key:             modernize-loop-convert.NamingStyle\n    value:           CamelCase\n  - key:             modernize-pass-by-value.IncludeStyle\n    value:           llvm\n  - key:             modernize-replace-auto-ptr.IncludeStyle\n    value:           llvm\n  - key:             modernize-use-default-member-init.UseAssignment\n    value:           '1'\n  - key:             modernize-use-emplace.IgnoreImplicitConstructors\n    value:           '1'\n  - key:             modernize-use-nullptr.NullMacros\n    value:           'NULL'\n  - key:             readability-braces-around-statements.ShortStatementLines\n    value:           '2'"
  },
  {
    "path": "wolf/.gitignore",
    "content": "*.DS_Store\n*.suo\n/build/*\n/shells/ffmpeg/build/*\n/rust/target/*"
  },
  {
    "path": "wolf/CMakeLists.txt",
    "content": "#cmake . -B build -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DANDROID_NDK=$ANDROID_NDK_HOME -DANDROID_PLATFORM=android-21 -DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a -DCMAKE_ANDROID_NDK=$ANDROID_NDK_HOME -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=21 -DCMAKE_BUILD_TYPE=Debug -GNinja\n#cd build\n#ninja\n\ncmake_minimum_required(VERSION 3.22...3.23)\n\n# set the name of the projects\nproject(wolf\n    DESCRIPTION \"Wolf Engine\"\n    LANGUAGES CXX\n)\n\nset(TEST_PROJECT_NAME \"${PROJECT_NAME}_tests\")\nmessage(\"CXX Compiler ID is ${CMAKE_CXX_COMPILER_ID}\")\n\n# set the options and enviroment variables\n#set(WEBRTC_SRC $ENV{WEBRTC_ROOT} CACHE STRING \"path to the root folder of webrtc folder\")\n\n#define includes, libs and srcs\nset(INCLUDES)\nset(LIBS PARENT_SCOPE) \nset(SRCS)\nset(TESTS_SRCS)\n\n# check the OS\nif(CMAKE_SIZEOF_VOID_P EQUAL 8)\n    if (WIN32)\n        set(WIN64 TRUE)\n    endif()\nendif()\n\nif(UNIX AND (NOT APPLE) AND (NOT EMSCRIPTEN))\n   set(LINUX TRUE)\nendif()\n\nif (MSVC AND NOT WIN64)\n    message( FATAL_ERROR \"Only Window 64 bit is supported\" )\nendif()\n\n# set target os\nif (WIN64)\n    set(TARGET_OS \"win\")\n    set(LIB_EXT \"lib\")\n    set(SHARED_EXT \"dll\")\nelseif(APPLE)\n    set(TARGET_OS \"mac\")\n    set(LIB_EXT \"a\")\n    set(SHARED_EXT \"dylib\")\nelseif(LINUX)\n    set(TARGET_OS \"linux\")\n    set(LIB_EXT \"a\")\n    set(SHARED_EXT \"so\")\nelseif (NOT EMSCRIPTEN)\n    message( FATAL_ERROR \"Unsuported OS, please open an issue at https://github.com/WolfEngine/WolfEngine\" )\nendif()\n\n# required packages\nfind_package(Git REQUIRED)\nif (NOT EMSCRIPTEN)\n    find_package (Threads)\nendif()\n\n# use folders\nset_property(GLOBAL PROPERTY USE_FOLDERS ON)\n\n# FetchContent for cloning repositories, avaiable since CMAKE 3.11\ninclude(FetchContent)\nset(FETCHCONTENT_QUIET OFF)\n\n# set type of library\nif (LINUX OR ANDROID_ABI)\n    set(LIBRARY_TYPE \"SHARED\")\nelse()\n    set(LIBRARY_TYPE \"STATIC\")\nendif()\n\nset(LIBRARY_TYPE \"${LIBRARY_TYPE}\" CACHE STRING \"Library type\")\n\n# Build options\nset(LIB_INSTALL_DIR lib CACHE STRING \"Install location of libraries\")\nset(BIN_INSTALL_DIR bin CACHE STRING \"Install location of executables\")\nset(INCLUDE_INSTALL_DIR include CACHE STRING \"Install location of executables\")\n\n# CMAKE GUI Options\nset(EMSDK \"$ENV{EMSDK}\" CACHE STRING \"Emscripten SDK path\")\nset(BOOST_VERSION \"1.82.0\" CACHE STRING \"Boost version tag\")\n\n# render module\noption(WOLF_RENDER \"Enable cross platform render engine based on Vulkan / OpenGL ES\" OFF)\n\n# media modules\noption(WOLF_MEDIA_FFMPEG \"Enable ffmpeg encoding and decoding\" OFF)\noption(WOLF_MEDIA_OPENAL \"Enable OpenAL soft\" OFF)\noption(WOLF_MEDIA_SCREEN_CAPTURE \"Enable screen capture\" OFF)\noption(WOLF_MEDIA_STB \"Enable stb headers\" OFF)\noption(WOLF_MEDIA_GSTREAMER \"Enable gstreamer wrapper\" OFF)\n\n# stream modules\noption(WOLF_STREAM_GRPC   \"Enable gRPC connection\" ON)\noption(WOLF_STREAM_QUIC   \"Enable QUIC\" OFF)\noption(WOLF_STREAM_RIST   \"Enable RIST streaming protocol\" OFF)\noption(WOLF_STREAM_WEBRTC \"Enable webRTC\" OFF)\n\n# system modules\noption(WOLF_SYSTEM_GAMEPAD_CLIENT \"Enable gamepad input handling\" OFF)\noption(WOLF_SYSTEM_GAMEPAD_VIRTUAL \"Enable virtual gamepad simulator\" OFF)\noption(WOLF_SYSTEM_HTTP_WS \"Enable http1.1 and websocket client/server based on boost beast or Emscripten\" OFF)\noption(WOLF_SYSTEM_LOG \"Enable log\" OFF)\noption(WOLF_SYSTEM_LZ4 \"Enable lz4 for compression\" OFF)\noption(WOLF_SYSTEM_LZMA \"Enable lzma for compression\" OFF)\noption(WOLF_SYSTEM_LUA \"Enable lua scripting language\" OFF)\noption(WOLF_SYSTEM_MIMALLOC \"Enable Microsoft's mimalloc memory allocator\" OFF)\noption(WOLF_SYSTEM_POSTGRESQL \"Enable postgresql database client\" OFF)\noption(WOLF_SYSTEM_PYTHON \"Enable embedded Python3 scripting\" OFF)\noption(WOLF_SYSTEM_SIG_SLOT \"Enable signal/slot based on boost signals2\" OFF)\noption(WOLF_SYSTEM_SOCKET \"Enable TCP/UDP protocol over socket\" OFF)\noption(WOLF_SYSTEM_OPENSSL \"Enable openSSL\" OFF)\noption(WOLF_SYSTEM_STACKTRACE \"Enable boost stacktrace\" OFF)\noption(WOLF_SYSTEM_ZLIB \"Enable Zlib compression library\" OFF)\n\n# machine learing modules\noption(WOLF_ML_NUDITY_DETECTION \"Enable machine learning nudity detection\" OFF)\noption(WOLF_ML_OCR \"Enable machine learning referee ocr\" OFF)\n\n#option(WOLF_ENABLE_LTO \"Enable cross language linking time optimization\" OFF)\noption(WOLF_TEST \"Enable tests\" ON)\nif (NOT MSVC)\n    option(WOLF_ENABLE_ASAN \"Enable ASAN\" OFF)\nendif()\n\nif(ENABLE_LTO)\n  include(CheckIPOSupported)\n  check_ipo_supported(RESULT supported OUTPUT error)\n  if(supported)\n      message(STATUS \"IPO / LTO enabled\")\n      set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)\n      add_link_options(-fuse-ld=lld)\n  else()\n      message(STATUS \"IPO / LTO not supported: <${error}>\")\n  endif()\nendif()\n\n# set C/CXX standards\nset(CMAKE_C_STANDARD 23)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\nset(CMAKE_CXX_EXTENSIONS ON)\nset(CMAKE_THREAD_PREFER_PTHREAD TRUE)\nset(THREADS_PREFER_PTHREAD_FLAG TRUE)\n\n#set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS \"Debug\" \"Release\" \"MinSizeRel\" \"RelWithDebInfo\")\nif (\"${CMAKE_BUILD_TYPE}\" STREQUAL \"\")\n  set(CMAKE_BUILD_TYPE \"Debug\")\nendif()\n\n# set C++ flags based on compiler\nif (CMAKE_CXX_COMPILER_ID STREQUAL \"Clang\" OR CMAKE_CXX_COMPILER_ID STREQUAL \"AppleClang\")\n  # using Clang or AppleClang\n  set(CMAKE_CXX_STANDARD 20)\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++2b -fexceptions -fcoroutines-ts\")\n  set(CMAKE_CXX_FLAGS_DEBUG \"-g\")\n  set(CMAKE_CXX_FLAGS_RELEASE \"-O3\")\nelseif (CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\")\n  # using GCC\n  set(CMAKE_CXX_STANDARD 23)\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++2b -fexceptions -fcoroutines\")\n  set(CMAKE_CXX_FLAGS_DEBUG \"-g\")\n  set(CMAKE_CXX_FLAGS_RELEASE \"-O3\")\nelseif (CMAKE_CXX_COMPILER_ID STREQUAL \"MSVC\")\n  # using Microsoft Visual C++\n  # set C++23 as the primary standard\n  set(CMAKE_CXX_STANDARD 23)\n  set(CMAKE_CXX_FLAGS \"/EHsc /W3 /bigobj\")\nendif()\n\nset(GETOPT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/system)\n\n# include cmakes\ninclude(cmake/vcpkg.cmake)\ninclude(cmake/system.cmake)\ninclude(cmake/stream.cmake)\ninclude(cmake/media.cmake)\ninclude(cmake/ml.cmake)\n\nif (EMSCRIPTEN)\n    message(WARNING \"WOLF_TEST will be disabled for Emscripten\")\n    set(WOLF_TEST OFF)\nelse()\n    # currently threads was not supported with WASM\n    list(APPEND LIBS Threads::Threads)\nendif()\n\n# disable build testing\nset(BUILD_TESTING OFF CACHE BOOL \"BUILD_TESTING\")\n\nif (WOLF_ENABLE_ASAN)\n    set(ENABLE_ASAN TRUE)\nendif()\n\n#add_compile_options(-fsanitize=address)\n#add_link_options(-fsanitize=address)\n\n# enabling clang-tidy\n# can be enabled with .CLANG-TIDY from Visual Studio Code\n# https://devblogs.microsoft.com/cppblog/visual-studio-code-c-december-2021-update-clang-tidy/\n# can be enabled with .CLANG-TIDY from Visual Studio\n# https://devblogs.microsoft.com/cppblog/code-analysis-with-clang-tidy-in-visual-studio/\n#set(CMAKE_C_CLANG_TIDY\n#     clang-tidy;\n#     -format-style=file;) \n#set(CMAKE_CXX_CLANG_TIDY\n#     clang-tidy;\n#     -format-style=file;)  \n\n# add definitions\n\nadd_definitions(\n    -DBOOST_ASIO_NO_DEPRECATED\n    -DBOOST_ASIO_HAS_CO_AWAIT\n    -DBOOST_ASIO_HAS_STD_COROUTINE \n)\nif (MSVC)\n    add_definitions(\n        -EHsc\n        -DNOMINMAX\n        -DWIN32_LEAN_AND_MEAN\n        -DWIN64\n        -DWIN32\n    )\nelseif (EMSCRIPTEN)\n    add_definitions(\n        -DEMSCRIPTEN\n    )\nelseif(APPLE)\n    add_definitions(-DNEED_XLOCALE_H=1)\nendif()\n\nif(CMAKE_BUILD_TYPE MATCHES Debug)\n    add_definitions(-DDEBUG -D_DEBUG)\nelse()\n    add_definitions(-DNDEBUG)\nendif()\n\n# setup Wolf definitions\nget_cmake_property(_vars VARIABLES)\nforeach (_var ${_vars})\n    string(FIND ${_var} \"WOLF_\" out)\n    if((\"${out}\" EQUAL 0) AND (\"(${${_var}}\" MATCHES ON))\n        add_definitions(\"-D${_var}\")\n    endif()\nendforeach()\n\n# include sources\nfile(GLOB_RECURSE WOLF_SRCS\n    \"${CMAKE_CURRENT_SOURCE_DIR}/wolf.cpp\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/wolf.hpp\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/DISABLE_ANALYSIS_BEGIN\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/DISABLE_ANALYSIS_END\"\n)\n\nfile(GLOB_RECURSE WOLF_PROTOS\n    \"${CMAKE_CURRENT_SOURCE_DIR}/protos/*\"\n)\n\nfile(GLOB_RECURSE WOLF_CMAKES\n    \"${CMAKE_CURRENT_SOURCE_DIR}/cmake/*\"\n)\n\n# includes\ninclude_directories(\n    ${INCLUDES}\n\t${CMAKE_CURRENT_SOURCE_DIR} \n\t${CMAKE_CURRENT_SOURCE_DIR}/../\n)\n\n# add source codes\nadd_library(${PROJECT_NAME} ${LIBRARY_TYPE} \n    ${SRCS}\n    ${WOLF_SRCS}\n    ${WOLF_CMAKES}\n    ${WOLF_PROTOS}\n)\n\nif (WOLF_STREAM_RIST)\n    add_dependencies(${PROJECT_NAME} ${RIST_TARGET})\nendif()\n\t\t\nif (MSVC OR WIN32)\n    if (LIBRARY_TYPE STREQUAL \"STATIC\")\n        set_property(TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY \"MultiThreaded$<$<CONFIG:Debug>:Debug>\")\n    else()\n        set_property(TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY \"MultiThreaded$<$<CONFIG:Debug>:Debug>DLL\")\n    endif()\nendif()\n\n# link libraries\ntarget_link_libraries(${PROJECT_NAME} PUBLIC ${LIBS})\n\n# create source group\nsource_group(\"wolf\" FILES ${WOLF_SRCS})\nsource_group(\"cmake\" FILES ${WOLF_CMAKES})\nsource_group(\"protos\" FILES ${WOLF_PROTOS})\nsource_group(\"stream/grpc\" FILES ${WOLF_STREAM_GRPC_SRC})\nsource_group(\"stream/janus\" FILES ${WOLF_STREAM_JANUS_SRC})\nsource_group(\"stream/test\" FILES ${WOLF_STREAM_TEST_SRC})\nsource_group(\"stream/quic\" FILES ${WOLF_STREAM_QUIC_SRC})\nsource_group(\"stream/rist\" FILES ${WOLF_STREAM_RIST_SRC})\nsource_group(\"stream/webrtc/capturer\" FILES ${WOLF_STREAM_WEBRTC_CAPTURER_SRC})\nsource_group(\"stream/webrtc/data\" FILES ${WOLF_STREAM_WEBRTC_DATA_SRC})\nsource_group(\"stream/webrtc/interceptor\" FILES ${WOLF_STREAM_WEBRTC_INTERCEPTOR_SRC})\nsource_group(\"stream/webrtc/media\" FILES ${WOLF_STREAM_WEBRTC_MEDIA_SRC})\nsource_group(\"stream/webrtc/peer\" FILES ${WOLF_STREAM_WEBRTC_PEER_SRC})\nsource_group(\"stream/test\" FILES ${WOLF_STREAM_QUIC_SRC})\nsource_group(\"stream\" FILES ${WOLF_STREAM_SRC})\nsource_group(\"system/gamepad\" FILES ${WOLF_SYSTEM_GAMEPAD_CLIENT_SRC} ${WOLF_SYSTEM_GAMEPAD_VIRTUAL_SRCS})\nsource_group(\"system/log\" FILES ${WOLF_SYSTEM_LOG_SRC})\nsource_group(\"system/compression\" FILES ${WOLF_SYSTEM_LZ4_SRCS} ${WOLF_SYSTEM_LZMA_SRCS})\nsource_group(\"system/script\" FILES ${WOLF_SYSTEM_LUA_SRC})\nsource_group(\"system/script\" FILES ${WOLF_SYSTEM_PYTHON_SRC})\nsource_group(\"system/socket\" FILES ${WOLF_SYSTEM_SOCKET_SRC} ${WOLF_SYSTEM_HTTP_WS_SRC})\nsource_group(\"system/test\" FILES ${WOLF_SYSTEM_TEST_SRC})\nsource_group(\"system\" FILES ${WOLF_SYSTEM_SRC})\nsource_group(\"media/test\" FILES ${WOLF_MEDIA_TEST_SRC})\nsource_group(\"media/ffmpeg\" FILES ${WOLF_MEDIA_FFMPEG_SRC})\nsource_group(\"media\" FILES ${WOLF_MEDIA_OPENAL_SRC} ${WOLF_MEDIA_STB_SRC})\nsource_group(\"ml/referee_ocr\" FILES ${WOLF_ML_OCR_SRC})\nsource_group(\"ml/nudity_detection\" FILES ${WOLF_ML_NUD_DET_SRC})\n\n# add compile options\nif (NOT WIN32)\n    target_compile_options(${PROJECT_NAME} PRIVATE -std=c++2b -fPIC)\nendif()\n\nif (WOLF_ENABLE_ASAN)\n    target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address)\n    target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address)\nendif()\n\n# build tests\nif (WOLF_TEST)\n    add_executable(${TEST_PROJECT_NAME}\n        tests.cpp\n        ${TESTS_SRCS}\n    )\n    \n    if (MSVC OR WIN32)\n        if (LIBRARY_TYPE STREQUAL \"STATIC\")\n            set_property(TARGET ${TEST_PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY \"MultiThreaded$<$<CONFIG:Debug>:Debug>\")\n        else()\n            set_property(TARGET ${TEST_PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY \"MultiThreaded$<$<CONFIG:Debug>:Debug>DLL\")\n        endif()\n    endif()\n\n    if(WOLF_ML_OCR AND LINUX)\n        target_link_libraries(${TEST_PROJECT_NAME} PRIVATE ${PROJECT_NAME} ${leptonica_BINARY_DIR}/install/lib/libleptonica.so)\n    else()\n        target_link_libraries(${TEST_PROJECT_NAME} PRIVATE ${PROJECT_NAME})\n    endif()\n\n    if (NOT WIN32)\n        target_compile_options(${TEST_PROJECT_NAME} PRIVATE -std=c++2b)\n    endif()\n\n    include(CTest)\n    add_test(NAME ${TEST_PROJECT_NAME} COMMAND ${TEST_PROJECT_NAME})\nendif()\n\nif(WOLF_ML_OCR AND WIN64)\n    add_custom_command(TARGET ${TEST_PROJECT_NAME} POST_BUILD\n        COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE} ${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}\n    )\nendif()\n\n# install target\ninstall(TARGETS ${PROJECT_NAME}\n    LIBRARY DESTINATION ${LIB_INSTALL_DIR}\n    ARCHIVE DESTINATION ${LIB_INSTALL_DIR})\n\t\nforeach(ITEM ${INCLUDES})\n  install(DIRECTORY ${ITEM}/ DESTINATION ${INCLUDE_INSTALL_DIR})\nendforeach()\n\ninstall(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wolf.hpp DESTINATION ${INCLUDE_INSTALL_DIR})\n\nif (WOLF_TEST)\n\tinstall(TARGETS ${TEST_PROJECT_NAME} DESTINATION ${BIN_INSTALL_DIR})\nendif()\n"
  },
  {
    "path": "wolf/DISABLE_ANALYSIS_BEGIN",
    "content": "#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning (disable:ALL_CODE_ANALYSIS_WARNINGS)\n#endif\n// NOLINTBEGIN\n"
  },
  {
    "path": "wolf/DISABLE_ANALYSIS_END",
    "content": "#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n// NOLINTEND"
  },
  {
    "path": "wolf/cmake/media.cmake",
    "content": " # link to ffmpeg\nif (WOLF_MEDIA_FFMPEG)\n  file(GLOB_RECURSE WOLF_MEDIA_FFMPEG_SRC\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/ffmpeg/*\"\n  )\n  list(APPEND SRCS ${WOLF_MEDIA_FFMPEG_SRC})\n  list(APPEND INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/third_party/ffmpeg/include)\n\n  list(APPEND FFMPEG_LIBS \n    avcodec \n    avdevice \n    avfilter\n    avformat\n    avutil\n    swresample\n    swscale\n    )\n\n  foreach (lib_name ${FFMPEG_LIBS})\n    list(APPEND LIBS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/ffmpeg/lib/${TARGET_OS}/${lib_name}.${LIB_EXT})\n  endforeach()\nendif()\n\n# link openAL\nif (WOLF_MEDIA_OPENAL)\n  message(\"fetching https://github.com/kcat/openal-soft.git\")\n \n  FetchContent_Declare(\n    openal\n    GIT_REPOSITORY https://github.com/kcat/openal-soft.git\n    GIT_TAG        master\n  )\n  \n  set(ALSOFT_EXAMPLES OFF CACHE BOOL \"ALSOFT_EXAMPLES\")\n  set(ALSOFT_INSTALL_EXAMPLES OFF CACHE BOOL \"ALSOFT_INSTALL_EXAMPLES\")\n  set(LIBTYPE \"STATIC\" CACHE STRING \"STATIC\")\n\n  set(FETCHCONTENT_QUIET OFF)\n  FetchContent_MakeAvailable(openal)\n  \n  file(GLOB_RECURSE WOLF_MEDIA_OPENAL_SRC\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/w_openal.hpp\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/w_openal.cpp\"\n  )\n   \n  list(APPEND SRCS ${WOLF_MEDIA_OPENAL_SRC})\n  list(APPEND INCLUDES ${openal_SOURCE_DIR}/include)\n  list(APPEND LIBS OpenAL::OpenAL)    \n\n  set_target_properties(\n    build_version\n    common\n    ex-common\n    OpenAL\n    openal-info\n    PROPERTIES FOLDER \"openAL\") \n\nendif()\n\nif (WOLF_MEDIA_STB)\n  message(\"fetching https://github.com/nothings/stb.git\")\n \n  FetchContent_Declare(\n    stb\n    GIT_REPOSITORY https://github.com/nothings/stb.git\n    GIT_TAG        master\n  )\n  \n  FetchContent_Populate(stb)\n\n  file(GLOB_RECURSE WOLF_MEDIA_STB_SRC\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/w_image.cpp\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/w_image.hpp\"\n  )\n\n  list(APPEND SRCS ${WOLF_MEDIA_STB_SRC})\n  list(APPEND INCLUDES ${stb_SOURCE_DIR})\n\nendif()\n\nif (WOLF_MEDIA_GSTREAMER)\n  file(GLOB_RECURSE WOLF_MEDIA_GSTREAMER_SRC\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/gst/*\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/gst/audio/*\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/gst/core/*\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/gst/elements/*\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/media/gst/video/*\"\n  )\n\n  find_package(PkgConfig REQUIRED)\n\n  pkg_check_modules(gstreamer REQUIRED IMPORTED_TARGET\n        gstreamer-1.0\n        gstreamer-video-1.0\n        gstreamer-audio-1.0)\n\n  add_library(gstreamer-lib INTERFACE)\n\n  target_compile_options(gstreamer-lib INTERFACE ${gstreamer_CFLAGS})\n  target_include_directories(gstreamer-lib INTERFACE ${gstreamer_INCLUDE_DIRS})\n  target_link_directories(gstreamer-lib BEFORE INTERFACE ${gstreamer_LIBRARY_DIRS})\n  target_link_libraries(gstreamer-lib INTERFACE ${gstreamer_LIBRARIES})\n\n  list(APPEND SRCS ${WOLF_MEDIA_GSTREAMER_SRC})\n  list(APPEND LIBS gstreamer-lib)\nendif()\n\nfile(GLOB_RECURSE WOLF_MEDIA_TEST_SRC\n\"${CMAKE_CURRENT_SOURCE_DIR}/media/test/*\"\n)\nlist(APPEND SRCS ${WOLF_MEDIA_TEST_SRC})\n"
  },
  {
    "path": "wolf/cmake/ml.cmake",
    "content": "if(WOLF_ML_OCR)\n    if(LINUX)\n        # fetch leptonica\n        message(\"fetching https://github.com/DanBloomberg/leptonica.git\")\n        FetchContent_Declare(\n            leptonica\n            GIT_REPOSITORY https://github.com/DanBloomberg/leptonica.git\n            GIT_TAG 1.80.0\n            GIT_SHALLOW TRUE\n            GIT_PROGRESS TRUE\n        )\n        FetchContent_Populate(leptonica)\n\n        add_custom_command(OUTPUT lept_config.out COMMAND cmake -B ${leptonica_BINARY_DIR} -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX:PATH=${leptonica_BINARY_DIR}/install ${leptonica_SOURCE_DIR})\n        add_custom_target(lept_config ALL DEPENDS lept_config.out)\n        add_custom_command(OUTPUT lept_build.out COMMAND cmake --build ${leptonica_BINARY_DIR} --target install)\n        add_custom_target(lept_build ALL DEPENDS lept_build.out)\n    endif()\n\n    # fetch tesseract\n    message(\"fetching https://github.com/tesseract-ocr/tesseract.git\")\n    FetchContent_Declare(\n        tesseract\n        GIT_REPOSITORY https://github.com/tesseract-ocr/tesseract.git\n        GIT_TAG main\n\n        GIT_SHALLOW TRUE\n        GIT_PROGRESS TRUE\n    )\n\n    if(WIN64)\n        set(FETCHCONTENT_QUIET OFF)\n\n        set(BUILD_TESTS OFF CACHE BOOL \"BUILD_TESTS\")\n        set(BUILD_TRAINING_TOOLS OFF CACHE BOOL \"BUILD_TRAINING_TOOLS\")\n        set(DISABLE_ARCHIVE ON CACHE BOOL \"DISABLE_ARCHIVE\")\n        set(DISABLE_CURL ON CACHE BOOL \"DISABLE_CURL\")\n        set(FAST_FLOAT ON CACHE BOOL \"FAST_FLOAT\")\n        set(GRAPHICS_DISABLED ON CACHE BOOL \"GRAPHICS_DISABLED\")\n        set(INSTALL_CONFIGS OFF CACHE BOOL \"INSTALL_CONFIGS\")\n        set(SW_BUILD ON CACHE BOOL \"SW_BUILD\")\n\n        FetchContent_MakeAvailable(tesseract)\n        list(APPEND INCLUDES\n            ${tesseract_SOURCE_DIR}/include\n            ${tesseract_BINARY_DIR}/include\n        )\n\n        if(\"${CMAKE_BUILD_TYPE}\" STREQUAL \"Debug\")\n            set(DEBUG_LIB_EXTENTION \"d\")\n        else()\n            set(DEBUG_LIB_EXTENTION \"\")\n        endif()\n\n        list(APPEND LIBS\n            ${tesseract_BINARY_DIR}/${CMAKE_BUILD_TYPE}/tesseract53${DEBUG_LIB_EXTENTION}.lib\n        )\n    elseif(LINUX)\n        FetchContent_Populate(tesseract)\n\n        list(APPEND INCLUDES\n            ${tesseract_SOURCE_DIR}/include\n            ${tesseract_BINARY_DIR}/install/include\n        )\n\n        link_directories(${tesseract_BINARY_DIR}/install/lib)\n        list(APPEND LIBS\n            tesseract\n        )\n\n        add_custom_command(OUTPUT tess_config.out COMMAND cmake -B ${tesseract_BINARY_DIR} -DBUILD_SHARED_LIBS=1 -DBUILD_TESTS=OFF -DBUILD_TRAINING_TOOLS=OFF -DDISABLE_ARCHIVE=ON -DDISABLE_CURL=ON -DFAST_FLOAT=ON -DGRAPHICS_DISABLED=ON -DINSTALL_CONFIGS=OFF -DLeptonica_DIR=${leptonica_BINARY_DIR} -DCMAKE_INSTALL_PREFIX:PATH=${tesseract_BINARY_DIR}/install ${tesseract_SOURCE_DIR})\n        add_custom_target(tess_config ALL DEPENDS tess_config.out)\n        add_custom_command(OUTPUT tess_build.out COMMAND cmake --build ${tesseract_BINARY_DIR} --target install)\n        add_custom_target(tess_build ALL DEPENDS tess_build.out)\n    endif()\n\n    # fetch opencv\n    message(\"fetching https://github.com/opencv/opencv.git\")\n    FetchContent_Declare(\n        opencv\n        GIT_REPOSITORY https://github.com/opencv/opencv.git\n        GIT_TAG 4.5.4\n        GIT_SHALLOW TRUE\n        GIT_PROGRESS TRUE\n    )\n\n    if(WIN64)\n        FetchContent_GetProperties(opencv)\n\n        set(BUILD_LIST core,highgui,videoio CACHE STRING \"BUILD_LIST\")\n        set(WITH_IPP OFF CACHE BOOL \"WITH_IPP\")\n        set(BUILD_EXAMPLES OFF CACHE BOOL \"BUILD_EXAMPLES\")\n        set(OPENCV_GENERATE_PKGCONFIG ON CACHE BOOL \"OPENCV_GENERATE_PKGCONFIG\")\n\n        FetchContent_MakeAvailable(opencv)\n\n        list(APPEND INCLUDES\n            ${CMAKE_BINARY_DIR}\n            ${opencv_SOURCE_DIR}/include\n            ${opencv_SOURCE_DIR}/modules/core/include\n            ${opencv_SOURCE_DIR}/modules/highgui/include\n            ${opencv_SOURCE_DIR}/modules/imgcodecs/include\n            ${opencv_SOURCE_DIR}/modules/imgproc/include\n            ${opencv_SOURCE_DIR}/modules/videoio/include\n        )\n        list(APPEND LIBS\n            ${opencv_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}/opencv_core454${DEBUG_LIB_EXTENTION}.lib\n            ${opencv_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}/opencv_highgui454${DEBUG_LIB_EXTENTION}.lib\n            ${opencv_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}/opencv_imgcodecs454${DEBUG_LIB_EXTENTION}.lib\n            ${opencv_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}/opencv_imgproc454${DEBUG_LIB_EXTENTION}.lib\n            ${opencv_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}/opencv_videoio454${DEBUG_LIB_EXTENTION}.lib\n        )\n    elseif(LINUX)\n        FetchContent_Populate(opencv)\n\n        list(APPEND INCLUDES\n            ${opencv_BINARY_DIR}/install/include/opencv4\n        )\n        list(APPEND LIBS\n            ${opencv_BINARY_DIR}/install/lib/libopencv_core.so\n            ${opencv_BINARY_DIR}/install/lib/libopencv_highgui.so\n            ${opencv_BINARY_DIR}/install/lib/libopencv_imgcodecs.so\n            ${opencv_BINARY_DIR}/install/lib/libopencv_imgproc.so\n            ${opencv_BINARY_DIR}/install/lib/libopencv_videoio.so\n        )\n\n        add_custom_command(OUTPUT opencv_config.out COMMAND cmake -B ${opencv_BINARY_DIR} -DBUILD_LIST=core,highgui,videoio -DBUILD_opencv_python3=OFF -DWITH_IPP=OFF -DBUILD_EXAMPLES=OFF -DOPENCV_GENERATE_PKGCONFIG=ON -DCMAKE_INSTALL_PREFIX:PATH=${opencv_BINARY_DIR}/install ${opencv_SOURCE_DIR})\n        add_custom_target(opencv_config ALL DEPENDS opencv_config.out)\n        add_custom_command(OUTPUT opencv_build.out COMMAND cmake --build ${opencv_BINARY_DIR} --target install)\n        add_custom_target(opencv_build ALL DEPENDS opencv_build.out)\n    endif()\n\n    # fetch rapidjson\n    message(\"fetching  https://github.com/Tencent/rapidjson.git\")\n    FetchContent_Declare(\n        rapidjson\n        GIT_REPOSITORY https://github.com/Tencent/rapidjson.git\n\n        GIT_SHALLOW TRUE\n        GIT_PROGRESS TRUE\n    )\n\n    FetchContent_Populate(rapidjson)\n\n    list(APPEND INCLUDES\n        ${rapidjson_SOURCE_DIR}/include\n    )\n\n    file(GLOB_RECURSE WOLF_ML_OCR_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/ml/referee_ocr/*\"\n    )\n\n    list(APPEND SRCS\n        ${WOLF_ML_OCR_SRC}\n    )\nendif()\n\nif(WOLF_ML_NUDITY_DETECTION)\n    # Set the C++ standard for the rest of the project\n    set(CMAKE_CXX_STANDARD 17)\n    set(CMAKE_CXX_STANDARD_REQUIRED ON)\n\n    # Find Torch package\n    find_package(Torch REQUIRED)\n\n    # Set the C++ standard for the rest of the project\n    set(CMAKE_CXX_STANDARD 23)\n    set(CMAKE_CXX_STANDARD_REQUIRED ON)\n\n    find_package(OpenCV REQUIRED)\n\n    list(APPEND INCLUDES\n        ${OpenCV_INCLUDE_DIRS}\n    )\n\n    list(APPEND LIBS\n        ${TORCH_LIBRARIES}\n        ${OpenCV_LIBS}\n    )\n\n    file(GLOB_RECURSE WOLF_ML_SHARED_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/ml/w_common.*\"\n    )\n\n    list(APPEND SRCS\n        ${WOLF_ML_SHARED_SRC}\n    )\n\n    file(GLOB_RECURSE WOLF_ML_NUD_DET_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/ml/nudity_detection/*\"\n    )\n\n    list(APPEND SRCS\n        ${WOLF_ML_NUD_DET_SRC}\n    )\nendif()"
  },
  {
    "path": "wolf/cmake/stream.cmake",
    "content": "# fetch gRPC\nif (WOLF_STREAM_GRPC)\n    if (EMSCRIPTEN)\n        message(FATAL_ERROR \"the wasm32 target is not supported for WOLF_STREAM_GRPC\")\n    endif()\n\n    vcpkg_install(asio-grpc asio-grpc TRUE)\n    list(APPEND LIBS asio-grpc::asio-grpc)\n\n    file(GLOB_RECURSE WOLF_STREAM_GRPC_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/stream/grpc/*\"\n    )\n\n    list(APPEND SRCS \n        ${WOLF_STREAM_GRPC_SRC}\n    )\n\n    if(WOLF_TEST)\n        add_library(generate-protos OBJECT)\n        \n        target_link_libraries(generate-protos PUBLIC protobuf::libprotobuf gRPC::grpc++_unsecure)\n        \n        set(PROTO_BINARY_DIR \"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/protos\")\n        set(PROTO_IMPORT_DIRS \"${CMAKE_CURRENT_SOURCE_DIR}/protos\")\n        \n        asio_grpc_protobuf_generate(\n            GENERATE_GRPC GENERATE_MOCK_CODE\n            TARGET generate-protos\n            USAGE_REQUIREMENT PUBLIC\n            IMPORT_DIRS ${PROTO_IMPORT_DIRS}\n            OUT_DIR \"${PROTO_BINARY_DIR}\"\n            PROTOS \"${CMAKE_CURRENT_SOURCE_DIR}/protos/raft.proto\")\n\n        list(APPEND INCLUDES \"${PROTO_BINARY_DIR}\")\n        list(APPEND TESTS_SRCS \n                \"${PROTO_BINARY_DIR}/raft.grpc.pb.cc\"\n                \"${PROTO_BINARY_DIR}/raft.pb.cc\"\n        )\n    endif()\n\nendif()\n\nif (WOLF_STREAM_JANUS)\n\n    file(GLOB_RECURSE WOLF_STREAM_JANUS_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/stream/janus/*\"\n    )\n\n    list(APPEND SRCS \n        ${WOLF_STREAM_JANUS_SRC}\n    )\n\nendif()\n\n# fetch msquic\nif (WOLF_STREAM_QUIC)\n    if (EMSCRIPTEN)\n        message(FATAL_ERROR \"WOLF_STREAM_QUIC is not supported for wasm32 target\")\n    endif()\n\n    if (NOT WIN32)\n        message(FATAL_ERROR \"WOLF_STREAM_QUIC feature is not avilable on non-windows yet.\")\n    endif()\n\n    file(GLOB_RECURSE WOLF_STREAM_QUIC_SRCS\n      \"${CMAKE_CURRENT_SOURCE_DIR}/stream/quic/*\"\n    )\n\n    if (WIN32 OR WIN64)\n        FetchContent_Declare(\n            msquic\n            URL https://github.com/microsoft/msquic/releases/download/v2.2.0/msquic_windows_x64_Release_schannel.zip\n            DOWNLOAD_EXTRACT_TIMESTAMP TRUE\n        )\n        FetchContent_Populate(msquic)\n    else()\n        message(FATAL_ERROR \"WOLF_STREAM_QUIC feature is not supported on target platform.\")\n    endif()\n\n    add_library(msquic-lib INTERFACE)\n    add_library(msquic::msquic ALIAS msquic-lib)\n    target_include_directories(msquic-lib INTERFACE ${msquic_SOURCE_DIR}/include)\n    target_link_directories(msquic-lib INTERFACE BEFORE ${msquic_SOURCE_DIR}/bin)\n    target_link_directories(msquic-lib INTERFACE BEFORE ${msquic_SOURCE_DIR}/lib)\n    target_link_libraries(msquic-lib INTERFACE msquic)\n\n    list(APPEND SRCS ${WOLF_STREAM_QUIC_SRCS})\n    list(APPEND LIBS msquic::msquic)\nendif()\n\nif (WOLF_STREAM_RIST)\n    if (EMSCRIPTEN)\n        message(FATAL_ERROR \"the wasm32 target is not supported for WOLF_STREAM_RIST\")\n    endif()\n\n    set(RIST_TARGET \"rist\")\n    message(\"fetching https://code.videolan.org/rist/librist.git\")\n    FetchContent_Declare(\n        ${RIST_TARGET}\n        GIT_REPOSITORY https://code.videolan.org/rist/librist.git\n        GIT_TAG        master\n      )\n    \n    set(FETCHCONTENT_QUIET OFF)\n    FetchContent_MakeAvailable(${RIST_TARGET})\n      \n    if (ANDROID)\n      add_custom_command(OUTPUT rist_command.out COMMAND\n      /bin/bash \"${CMAKE_CURRENT_SOURCE_DIR}/third_party/shells/librist/librist-android.sh\" --build_dir=${rist_BINARY_DIR}\n       WORKING_DIRECTORY ${rist_SOURCE_DIR})\n      add_custom_target(rist ALL DEPENDS rist_command.out)\n      \n      list(APPEND LIBS\n        ${rist_BINARY_DIR}/librist.a)\n    else ()\n      STRING(TOLOWER \"${CMAKE_BUILD_TYPE}\" CMAKE_BUILD_TYPE_LOWER)\n      \n      add_custom_command(OUTPUT rist_command.out COMMAND cmd /c \"meson setup ${rist_BINARY_DIR} --backend vs2022 --default-library static --buildtype ${CMAKE_BUILD_TYPE_LOWER} & meson compile -C ${rist_BINARY_DIR}\" WORKING_DIRECTORY ${rist_SOURCE_DIR})\n      add_custom_target(rist ALL DEPENDS rist_command.out)\n\n      list(APPEND LIBS\n        ws2_32\n        ${rist_BINARY_DIR}/librist.a)\n        \n    endif()\n    \n    list(APPEND INCLUDES\n        ${rist_BINARY_DIR}\n        ${rist_BINARY_DIR}/include\n        ${rist_BINARY_DIR}/include/librist\n        ${rist_SOURCE_DIR}/contrib\n        ${rist_SOURCE_DIR}/contrib/mbedtls/include\n        ${rist_SOURCE_DIR}/include\n        ${rist_SOURCE_DIR}/include/librist\n        ${rist_SOURCE_DIR}/src\n      )\n      \n      file(GLOB_RECURSE WOLF_STREAM_RIST_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/stream/rist/*\"\n      )\n      list(APPEND SRCS ${WOLF_STREAM_RIST_SRC})\nendif()\n\nif (WOLF_STREAM_WEBRTC)\n    if (EMSCRIPTEN)\n        message(FATAL_ERROR \"the wasm32 target is not supported for WOLF_STREAM_WEBRTC\")\n    endif()\n\n    # we need http & json for webrtc\n    \n    if (NOT WOLF_SYSTEM_JSON)\n        message( FATAL_ERROR \"'WOLF_STREAM_WEBRTC' needs 'WOLF_SYSTEM_JSON' = ON\" )\n    endif()\n\n    if (NOT WOLF_STREAM_HTTP)\n        message( FATAL_ERROR \"'WOLF_STREAM_WEBRTC' needs 'WOLF_STREAM_HTTP' = ON\" )\n    endif()\n   \n    list(APPEND INCLUDES\n        ${WEBRTC_SRC}\n        ${WEBRTC_SRC}/third_party/abseil-cpp\n        ${WEBRTC_SRC}/third_party/libyuv/include\n    )\n    if (WIN32)\n        # enable/disable debug option\n        if(CMAKE_BUILD_TYPE MATCHES Debug)\n            add_definitions(\n                -D_HAS_ITERATOR_DEBUGGING=1\n                -D_ITERATOR_DEBUG_LEVEL=2\n            )\n        else()\n            add_definitions(\n                -D_HAS_ITERATOR_DEBUGGING=0\n                -D_ITERATOR_DEBUG_LEVEL=0\n            )\n        endif()\n\n        add_definitions(\n            -DWEBRTC_WIN \n            -D__PRETTY_FUNCTION__=__FUNCTION__\n            #-DUSE_X11 \n            #-D_WINSOCKAPI_\n            -DHAVE_SOUND) \n\n        list(APPEND LIBS\n            d3d11 \n            dmoguids \n            dwmapi\n            dxgi \n            iphlpapi \n            msdmo \n            secur32 \n            strmiids \n            winmm \n            wmcodecdspuuid \n        )\n    elseif (APPLE)\n\n        add_definitions(\n            -DHAVE_SOUND \n            -DWEBRTC_MAC \n            -DWEBRTC_POSIX \n            -fno-rtti)\n        \n        find_library(APPLICATION_SERVICES ApplicationServices)\n        find_library(AUDIO_TOOLBOX AudioToolBox)\n        find_library(CORE_AUDIO CoreAudio)\n        find_library(CORE_FOUNDATION CoreFoundation)\n        find_library(CORE_SERVICES CoreServices)\n        find_library(FOUNDATION Foundation)\n\n        list(APPEND LIBS\n            ${APPLICATION_SERVICES} \n            ${AUDIO_TOOLBOX} \n            ${CORE_AUDIO} \n            ${CORE_FOUNDATION} \n            ${CORE_SERVICES}\n            ${FOUNDATION} \n        )\n    endif()\n    add_definitions(-DHAVE_JPEG)\n    link_directories(${WEBRTC_SRC}/out/${TARGET_OS}/${CMAKE_BUILD_TYPE}/obj/)\n    list(APPEND LIBS webrtc)\n\n    file(GLOB_RECURSE WOLF_STREAM_WEBRTC_CAPTURER_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/stream/webrtc/capturer/*\"\n    )\n    file(GLOB_RECURSE WOLF_STREAM_WEBRTC_DATA_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/stream/webrtc/data/*\"\n    )\n    file(GLOB_RECURSE WOLF_STREAM_WEBRTC_INTERCEPTOR_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/stream/webrtc/interceptor/*\"\n    )\n    file(GLOB_RECURSE WOLF_STREAM_WEBRTC_MEDIA_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/stream/webrtc/media/*\"\n    )\n    file(GLOB_RECURSE WOLF_STREAM_WEBRTC_PEER_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/stream/webrtc/peer/*\"\n    )\n\n    list(APPEND SRCS \n        ${WOLF_STREAM_WEBRTC_CAPTURER_SRC}\n        ${WOLF_STREAM_WEBRTC_DATA_SRC}\n        ${WOLF_STREAM_WEBRTC_INTERCEPTOR_SRC}\n        ${WOLF_STREAM_WEBRTC_MEDIA_SRC}\n        ${WOLF_STREAM_WEBRTC_PEER_SRC}\n    )\nendif()\n\nfile(GLOB_RECURSE WOLF_STREAM_TEST_SRC\n    \"${CMAKE_CURRENT_SOURCE_DIR}/stream/test/*\"\n)\nlist(APPEND SRCS ${WOLF_STREAM_TEST_SRC})\n\n"
  },
  {
    "path": "wolf/cmake/system.cmake",
    "content": "if (WOLF_SYSTEM_STACKTRACE)\n    if (EMSCRIPTEN)\n        message(FATAL_ERROR \"the wasm32 target is not supported for WOLF_SYSTEM_STACKTRACE\")\n    elseif(NOT MSVC)\n        message(FATAL_ERROR \"WOLF_SYSTEM_STACKTRACE is only supported on Visual C++\")\n    endif()\nendif()\n\n\n# fetch mimalloc\nif (WOLF_SYSTEM_MIMALLOC)\n    if (EMSCRIPTEN)\n        message(FATAL_ERROR \"the wasm32 target is not supported for WOLF_SYSTEM_MIMALLOC\")\n    endif()\n    vcpkg_install(mimalloc mimalloc TRUE)\n    list(APPEND LIBS mimalloc)\nendif()\n\n# fetch boost components via vcpkg\nif (EMSCRIPTEN)\n    execute_process(COMMAND vcpkg install \n        boost-leaf \n        boost-signals2 --triplet=${VCPKG_TARGET_TRIPLET})\nelseif(WOLF_SYSTEM_PYTHON)\n    execute_process(COMMAND vcpkg install \n        boost-asio \n        boost-beast \n        boost-leaf \n        boost-python\n        boost-signals2 \n        boost-test --triplet=${VCPKG_TARGET_TRIPLET})\nelse()\n    execute_process(COMMAND vcpkg install \n        boost-asio \n        boost-beast \n        boost-leaf \n        boost-signals2 \n        boost-test --triplet=${VCPKG_TARGET_TRIPLET})\nendif()\n\nset(Boost_INCLUDE_DIR $ENV{VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/include CACHE STRING \"boost include directory\" FORCE)\nlist(APPEND INCLUDES ${Boost_INCLUDE_DIR})\nfind_package(Boost ${Boost_VERSION} REQUIRED)\n\n# install gsl\nvcpkg_install(Microsoft.GSL ms-gsl TRUE)\nlist(APPEND LIBS Microsoft.GSL::GSL)\n\nif (NOT CMAKE_CXX_COMPILER_ID STREQUAL \"MSVC\" AND NOT EMSCRIPTEN)\n    vcpkg_install(fmt fmt FALSE)\n    list(APPEND LIBS fmt::fmt-header-only)\nendif()\n\nif (WOLF_SYSTEM_GAMEPAD_CLIENT)\n    file(GLOB_RECURSE WOLF_SYSTEM_GAMEPAD_CLIENT_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_client_emc.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_client_keymap.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_client_sdl.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_client_types.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_client.hpp\"\n    )\n    list(APPEND SRCS ${WOLF_SYSTEM_GAMEPAD_CLIENT_SRC})\n\n    if (NOT EMSCRIPTEN)\n        message(\"fetching https://github.com/libsdl-org/SDL\")\n        FetchContent_Declare(\n            SDL3-static\n            GIT_REPOSITORY https://github.com/libsdl-org/SDL\n            GIT_TAG        main\n        )\n\n        set(SDL_AUDIO OFF CACHE BOOL \"SDL_AUDIO\")\n        set(SDL_DIRECTX OFF CACHE BOOL \"SDL_DIRECTX\")\n        set(SDL_DISKAUDIO OFF CACHE BOOL \"SDL_DISKAUDIO\")\n        set(SDL_DUMMYAUDIO OFF CACHE BOOL \"SDL_DUMMYAUDIO\")\n        set(SDL_DUMMYVIDEO OFF CACHE BOOL \"SDL_DUMMYVIDEO\")\n        set(SDL_FILE OFF CACHE BOOL \"SDL_FILE\")\n        set(SDL_FILESYSTEM OFF CACHE BOOL \"SDL_FILESYSTEM\")\n        set(SDL_METAL OFF CACHE BOOL \"SDL_METAL\")\n        set(SDL_OFFSCREEN OFF CACHE BOOL \"SDL_OFFSCREEN\")\n        set(SDL_OPENGL OFF CACHE BOOL \"SDL_OPENGL\")\n        set(SDL_OPENGLES OFF CACHE BOOL \"SDL_OPENGLES\")\n        set(SDL_RENDER OFF CACHE BOOL \"SDL_RENDER\")\n        set(SDL_RENDER_D3D OFF CACHE BOOL \"SDL_RENDER_D3D\")\n        set(SDL_RENDER_METAL OFF CACHE BOOL \"SDL_RENDER_METAL\")\n        set(SDL_SHARED OFF CACHE BOOL \"SDL_SHARED\")\n        set(SDL_TEST OFF CACHE BOOL \"SDL_TEST\")\n        set(SDL_TESTS OFF CACHE BOOL \"SDL_TESTS\")\n        set(SDL_VIDEO OFF CACHE BOOL \"SDL_VIDEO\")\n        set(SDL_VULKAN OFF CACHE BOOL \"SDL_VULKAN\")\n        set(SDL_WASAPI OFF CACHE BOOL \"SDL_WASAPI\")\n\n        set(SDL_HIGHDAPI_JOYSTICK ON CACHE BOOL \"SDL_HIGHDAPI_JOYSTICK\")\n        set(SDL_JOYSTICK ON CACHE BOOL \"SDL_JOYSTICK\")\n        set(SDL_STATIC ON CACHE BOOL \"SDL_STATIC\")\n        set(SDL_XINPUT ON CACHE BOOL \"SDL_XINPUT\")\n\n        set(FETCHCONTENT_QUIET OFF)\n        FetchContent_MakeAvailable(SDL3-static)\n\n        list(APPEND INCLUDES\n            ${SDL3-static_SOURCE_DIR}/include\n            )\n        list(APPEND LIBS SDL3-static)\n\n        set_target_properties(\n            SDL3-static\n            uninstall\n            PROPERTIES FOLDER \"SDL\") \n    endif()\nendif()\n\nif (WOLF_SYSTEM_GAMEPAD_VIRTUAL)\n  if (NOT WIN32)\n    message(SEND_ERROR \"WOLF_SYSTEM_GAMEPAD_VIRTUAL can only build for Windows\")\n  else()\n    message(\"fetching https://github.com/ViGEm/ViGEmClient.git\")\n    FetchContent_Declare(\n      ViGEmClient\n      GIT_REPOSITORY https://github.com/ViGEm/ViGEmClient.git\n      GIT_TAG        master\n    )\n    FetchContent_MakeAvailable(ViGEmClient)\n\n    file(GLOB_RECURSE WOLF_SYSTEM_GAMEPAD_VIRTUAL_SRCS\n      \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_virtual_pool.cpp\"\n      \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_virtual_pool.hpp\"\n      \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_virtual.cpp\"\n      \"${CMAKE_CURRENT_SOURCE_DIR}/system/gamepad/w_gamepad_virtual.hpp\"\n    )\n    list(APPEND SRCS ${WOLF_SYSTEM_GAMEPAD_VIRTUAL_SRCS})\n    list(APPEND INCLUDES ${ViGEmClient_SOURCE_DIR}/include)\n    list(APPEND LIBS \n      ViGEmClient\n      Xinput.lib \n      SetupAPI.lib)\n   endif()\nendif()\n\nif (WOLF_SYSTEM_LOG)\n    if (EMSCRIPTEN)\n        message(FATAL_ERROR \"the wasm32 target is not supported for WOLF_SYSTEM_LOG\")\n    endif()\n\n    vcpkg_install(spdlog spdlog TRUE)\n    list(APPEND LIBS spdlog::spdlog spdlog::spdlog_header_only)\n\n    file(GLOB_RECURSE WOLF_SYSTEM_LOG_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/log/*\"\n    )\n    list(APPEND SRCS ${WOLF_SYSTEM_LOG_SRC})\nendif()\n\nif (WOLF_SYSTEM_LZ4)\n  if (EMSCRIPTEN)\n        message(FATAL_ERROR \"the wasm32 target is not supported for WOLF_SYSTEM_LZ4\")\n  endif()\n  vcpkg_install(lz4 lz4 TRUE)\n  list(APPEND LIBS lz4::lz4)\n\n  file(GLOB_RECURSE WOLF_SYSTEM_LZ4_SRCS\n    \"${CMAKE_CURRENT_SOURCE_DIR}/system/compression/w_lz4.cpp\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/system/compression/w_lz4.hpp\"\n  )\n  list(APPEND SRCS ${WOLF_SYSTEM_LZ4_SRCS})\nendif()\n\nif (WOLF_SYSTEM_LZMA)\n  if (EMSCRIPTEN)\n        message(FATAL_ERROR \"the wasm32 target is not supported for WOLF_SYSTEM_LZMA\")\n  endif()\n  message(\"fetching https://github.com/WolfEngine/lzma.git\")\n  FetchContent_Declare(\n    lzma\n    GIT_REPOSITORY https://github.com/WolfEngine/lzma.git\n    GIT_TAG        main\n  )\n  set(FETCHCONTENT_QUIET OFF)\n  FetchContent_MakeAvailable(lzma)\n\n  file(GLOB_RECURSE WOLF_SYSTEM_LZMA_SRCS\n    \"${CMAKE_CURRENT_SOURCE_DIR}/system/compression/w_lzma.cpp\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/system/compression/w_lzma.hpp\"\n  )\n  list(APPEND SRCS ${WOLF_SYSTEM_LZMA_SRCS})\n  list(APPEND INCLUDES ${lzma_SOURCE_DIR}/src)\n  list(APPEND LIBS lzma)  \nendif()\n\n# include openSSL\nif (WOLF_SYSTEM_OPENSSL AND NOT EMSCRIPTEN)\n    vcpkg_install(OpenSSL openssl FALSE)\n    list(APPEND LIBS OpenSSL::SSL OpenSSL::Crypto)\nendif()\n\n# include socket/websocket sources\nif (WOLF_SYSTEM_SOCKET AND NOT EMSCRIPTEN)    \n    file(GLOB_RECURSE WOLF_SYSTEM_SOCKET_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_socket_options.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_tcp_client.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_tcp_client.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_tcp_server.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_tcp_server.hpp\"\n    )\n    list(APPEND SRCS ${WOLF_SYSTEM_SOCKET_SRC})\nendif()\n\nif (WOLF_SYSTEM_HTTP_WS)\n    if (EMSCRIPTEN)\n        file(GLOB_RECURSE WOLF_SYSTEM_HTTP_WS_SRC\n            \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_ws_client_emc.cpp\"\n            \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_ws_client_emc.hpp\"\n        )\n    else()\n        file(GLOB_RECURSE WOLF_SYSTEM_HTTP_WS_SRC\n            \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_ws_client.cpp\"\n            \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_ws_client.hpp\"\n            \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_ws_server.cpp\"\n            \"${CMAKE_CURRENT_SOURCE_DIR}/system/socket/w_ws_server.hpp\"\n        )\n    endif()\n    list(APPEND SRCS ${WOLF_SYSTEM_HTTP_WS_SRC})\nendif()\n\nif (WOLF_SYSTEM_ZLIB)\n    vcpkg_install(ZLIB zlib FALSE)\n    list(APPEND LIBS ZLIB::ZLIB)\nendif()\n\nif (WOLF_SYSTEM_POSTGRESQL)\n    vcpkg_install(libpq libpq TRUE)\n    list(APPEND LIBS libpq::libpq)\n\n    file(GLOB_RECURSE WOLF_SYSTEM_POSTGRESQL_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/db/w_postgresql.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/db/w_postgresql.hpp\"\n    )\n    list(APPEND LIBS PostgreSQL::PostgreSQL)\nendif()\n\nif (WOLF_SYSTEM_LUA)\n    vcpkg_install(Lua lua FALSE)\n    vcpkg_install(sol2 sol2 TRUE)\n\n    list(APPEND LIBS lua sol2)\n    \n    file(GLOB_RECURSE WOLF_SYSTEM_LUA_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/script/w_lua.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/script/w_lua.hpp\"\n    )\n    \n    list(APPEND SRCS \n        ${WOLF_SYSTEM_LUA_SRC}\n    )\nendif()\n\nif (WOLF_SYSTEM_PYTHON)\n    find_package(Python3 REQUIRED COMPONENTS Development)\n    find_package(Boost REQUIRED COMPONENTS python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR})\n\n    file(GLOB_RECURSE WOLF_SYSTEM_PYTHON_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/script/w_python.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/script/w_python.hpp\"\n    )\n    list(APPEND SRCS\n        ${WOLF_SYSTEM_PYTHON_SRC}\n    )\n    list(APPEND INCLUDES ${Python3_INCLUDE_DIRS})\n    list(APPEND LIBS Python3::Python Boost::python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR})\n\n    get_filename_component(PYTHON_HOME ${Python3_EXECUTABLE} DIRECTORY)\n    add_definitions(\n        -DBOOST_PYTHON_STATIC_LIB\n        -DPYTHON_HOME=\"${PYTHON_HOME}\"\n    )\nendif()\n\nif (EMSCRIPTEN)\n    file (GLOB_RECURSE WOLF_SYSTEM_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_gametime.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_gametime.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_trace.hpp\"\n    )\nelse()\n    file (GLOB_RECURSE WOLF_SYSTEM_SRC\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/getopt.h\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_gametime.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_gametime.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_leak_detector.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_leak_detector.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_process.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_process.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_time.cpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_time.hpp\"\n        \"${CMAKE_CURRENT_SOURCE_DIR}/system/w_trace.hpp\"\n    )\nendif()\n\nfile(GLOB_RECURSE WOLF_SYSTEM_TEST_SRC\n    \"${CMAKE_CURRENT_SOURCE_DIR}/system/test/*\"\n)\n\nlist(APPEND SRCS \n    ${WOLF_SYSTEM_SRC} \n    ${WOLF_SYSTEM_TEST_SRC}\n)\n"
  },
  {
    "path": "wolf/cmake/vcpkg.cmake",
    "content": "if(NOT DEFINED ENV{VCPKG_ROOT})\n    message(FATAL_ERROR \"VCPKG_ROOT environment variable is not set.\")\nendif()\n\nif(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)\n    if(CMAKE_TOOLCHAIN_FILE MATCHES \"android_x86_64\")\n        set(vcpkg_triplet \"x64-android\")\n    elseif(CMAKE_TOOLCHAIN_FILE MATCHES \"android_x86\")\n        set(vcpkg_triplet \"x86-android\")\n    elseif(CMAKE_TOOLCHAIN_FILE MATCHES \"android_arm64_v8a\")\n        set(vcpkg_triplet \"arm64-android\")\n    elseif(CMAKE_TOOLCHAIN_FILE MATCHES \"android_armv7\")\n        set(vcpkg_triplet \"arm-neon-android\")\n    endif()\nelseif(ANDROID_ABI)\n    if(ANDROID_ABI STREQUAL \"x86_64\")\n        set(vcpkg_triplet \"x64-android\")\n    elseif(ANDROID_ABI STREQUAL \"x86\")\n        set(vcpkg_triplet \"x86-android\")\n    elseif(ANDROID_ABI STREQUAL \"arm64-v8a\")\n        set(vcpkg_triplet \"arm64-android\")\n    elseif(ANDROID_ABI STREQUAL \"armeabi-v7a\")\n        set(vcpkg_triplet \"arm-neon-android\")\n    endif()\nelseif(EMSCRIPTEN)\n    set(vcpkg_triplet \"wasm32-emscripten\")\nelse() # desktop\n    if(WIN32)\n        set(vcpkg_triplet \"x64-windows\")\n    elseif(APPLE)\n        set(vcpkg_triplet \"x64-osx\")\n    elseif(UNIX)\n        set(vcpkg_triplet \"x64-linux\")\n    endif()\nendif()\n\nset(CMAKE_TOOLCHAIN_FILE \"$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\")\nif (LIBRARY_TYPE STREQUAL \"STATIC\" AND NOT EMSCRIPTEN)\n    set(VCPKG_TARGET_TRIPLET ${vcpkg_triplet}-static CACHE STRING \"vcpkg target triplet\" FORCE)\nelse()\n    set(VCPKG_TARGET_TRIPLET ${vcpkg_triplet} CACHE STRING \"vcpkg target triplet\" FORCE)\nendif()\n\ninclude(\"$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake\")\n\nfunction(vcpkg_install PACKAGE PACKAGE_NAME WITH_CONFIG)\n    message(STATUS \"finding ${PACKAGE}\")\n    if (WITH_CONFIG)\n        find_package(${PACKAGE} CONFIG)\n    else()\n        find_package(${PACKAGE})\n    endif()\n    if(NOT ${PACKAGE}_FOUND)\n        message(STATUS \"installing ${PACKAGE} via vcpkg\")\n        execute_process(COMMAND vcpkg install ${PACKAGE_NAME} --triplet=${VCPKG_TARGET_TRIPLET})\n        if (WITH_CONFIG)\n            find_package(${PACKAGE} CONFIG REQUIRED)\n        else()\n            find_package(${PACKAGE} REQUIRED)\n        endif()\n    endif()\nendfunction()\n"
  },
  {
    "path": "wolf/media/ffmpeg/w_av_config.cpp",
    "content": "#include \"w_av_config.hpp\"\n\nusing w_av_config = wolf::media::ffmpeg::w_av_config;\n\nw_av_config::w_av_config(_In_ AVPixelFormat p_format, _In_ int p_width, _In_ int p_height,\n                         _In_ int p_alignment) noexcept\n    : format(p_format), width(p_width), height(p_height), alignment(p_alignment) {}\n\nw_av_config::w_av_config(_In_ int p_nb_channels, _In_ AVSampleFormat p_sample_fmts,\n                         _In_ int p_sample_rate) noexcept\n    : sample_rate(p_sample_rate), sample_fmts(p_sample_fmts), nb_channels(p_nb_channels) {}\n\nint w_av_config::get_required_video_buffer_size() const noexcept {\n  return av_image_get_buffer_size(this->format, this->width, this->height, this->alignment);\n}\n"
  },
  {
    "path": "wolf/media/ffmpeg/w_av_config.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright  2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_FFMPEG\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n\nextern \"C\" {\n#include <libavformat/avformat.h>\n#include <libavutil/imgutils.h>\n}\n\nnamespace wolf::media::ffmpeg {\nclass w_av_config {\n public:\n#pragma region Constructors /Destructor\n  // default constructor\n  W_API w_av_config() noexcept = default;\n\n  // constructor for av video format\n  W_API w_av_config(_In_ AVPixelFormat p_format, _In_ int p_width, _In_ int p_height,\n                    _In_ int p_alignment = 1) noexcept;\n\n  // constructor for av audio format\n  W_API w_av_config(_In_ int p_nb_channels, _In_ AVSampleFormat p_sample_fmts,\n                    _In_ int p_sample_rate) noexcept;\n\n  // destructor\n  W_API virtual ~w_av_config() noexcept = default;\n\n  // move constructor.\n  W_API w_av_config(w_av_config &&p_other) noexcept = default;\n  // move assignment operator.\n  W_API w_av_config &operator=(w_av_config &&p_other) noexcept = default;\n\n  // copy constructor\n  w_av_config(const w_av_config &p_other) noexcept = default;\n  // copy assignment operator\n  w_av_config &operator=(const w_av_config &p_other) noexcept = default;\n#pragma endregion\n\n  /**\n   * @returns the required buffer size for video frame\n   */\n  W_API int get_required_video_buffer_size() const noexcept;\n\n  // the format of av frame\n  AVPixelFormat format = AVPixelFormat::AV_PIX_FMT_NONE;\n  // the width of av frame\n  int width = 0;\n  // the height of av frame\n  int height = 0;\n  // data alignment\n  int alignment = 0;\n  // the sample rate of the audio\n  int sample_rate = 0;\n  // the sample format of the audio\n  AVSampleFormat sample_fmts = AVSampleFormat::AV_SAMPLE_FMT_NONE;\n  // number of channels\n  int nb_channels = 0;\n};\n}  // namespace wolf::media::ffmpeg \n\n#endif  // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_av_format.cpp",
    "content": "#ifdef WOLF_MEDIA_FFMPEG\n\n#include \"w_av_format.hpp\"\n#include \"w_av_frame.hpp\"\n\nusing w_av_format = wolf::media::ffmpeg::w_av_format;\n\nw_av_format::w_av_format() noexcept\n    : _stream_buffer(nullptr), _fmt_ctx(nullptr), _io_ctx(nullptr) {}\n\nvoid w_av_format::_release() noexcept {\n  if (this->_stream_buffer != nullptr) {\n    auto _ptr = this->_stream_buffer.get();\n    free(_ptr);\n    this->_stream_buffer = nullptr;\n  }\n  if (this->_fmt_ctx != nullptr) {\n    auto _ptr = this->_fmt_ctx.get();\n    avformat_close_input(&_ptr);\n    this->_stream_buffer = nullptr;\n  }\n  if (this->_io_ctx != nullptr) {\n    auto _ptr = this->_io_ctx.get();\n    av_free(_ptr);\n    this->_stream_buffer = nullptr;\n  }\n}\n\nstatic int s_read_packet(void *p_opaque, _Inout_ uint8_t *p_buf, _In_ int p_buf_size) {\n  auto _av_fmt = gsl::narrow_cast<w_av_format *>(p_opaque);\n  if (_av_fmt) {\n    if (_av_fmt->on_read_callback) {\n      return _av_fmt->on_read_callback(p_buf, p_buf_size);\n    }\n  }\n  return -1;  // failed\n}\n\nboost::leaf::result<int> w_av_format::init(_In_ int p_stream_buf_size) noexcept {\n  _release();\n\n  // alloc a buffer for the stream\n  auto _ptr = gsl::narrow_cast<uint8_t *>(malloc(p_stream_buf_size));\n  if (_ptr == nullptr) {\n    // out of memory\n    return W_FAILURE(std::errc::not_enough_memory, \"could not allocate memory for stream buffer\");\n  }\n  this->_stream_buffer.reset(_ptr);\n\n  // get a AVContext stream\n  auto _io_ctx_ptr =\n      avio_alloc_context(this->_stream_buffer.get(),  // buffer\n                         p_stream_buf_size,           // buffer size\n                         0,              // buffer is only readable - set to 1 for read/write\n                         this,           // use your specified data\n                         s_read_packet,  // function - reading Packets (see example)\n                         nullptr,        // function - write Packets\n                         nullptr         // function - seek to position in stream (see example)\n      );\n  if (_io_ctx_ptr == nullptr) {\n    // out of memory\n    return W_FAILURE(std::errc::not_enough_memory, \"could not allocate io context\");\n  }\n  this->_io_ctx.reset(_io_ctx_ptr);\n\n  // allocate a AVContext\n  auto _fmt_ctx_ptr = avformat_alloc_context();\n  if (_fmt_ctx_ptr == nullptr) {\n    // out of memory\n    return W_FAILURE(std::errc::not_enough_memory, \"could not allocate avformat context\");\n  }\n  this->_fmt_ctx.reset(_fmt_ctx_ptr);\n\n  // Set up the format context based on custom IO\n  this->_fmt_ctx->pb = _io_ctx_ptr;\n  this->_fmt_ctx->flags |= AVFMT_FLAG_CUSTOM_IO;\n\n  // open \"file\" (open our custom IO)\n  // empty string is where filename would go. doesn't matter since we aren't\n  // reading a file NULL params are format and demuxer settings, respectively\n  if (avformat_open_input(&_fmt_ctx_ptr, \"\", nullptr, nullptr) < 0) {\n    // error on opening input\n    return W_FAILURE(std::errc::not_enough_memory, \"could not allocate io context\");\n  }\n\n  // find the stream info\n  if (avformat_find_stream_info(_fmt_ctx_ptr, nullptr) < 0) {\n    // Error on finding stream info\n    return W_FAILURE(std::errc::operation_canceled, \"could not get stream info\");\n  }\n\n  // find best stream\n  const auto _ret =\n      av_find_best_stream(_fmt_ctx_ptr, AVMediaType::AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);\n  if (_ret < 0) {\n    // Error on finding stream info\n    return W_FAILURE(std::errc::operation_canceled, \"could not find best stream\");\n  }\n\n  return 0;\n}\n\nuint8_t *w_av_format::get_io_ctx_buffer() const {\n  if (this->_io_ctx) {\n    return this->_io_ctx->buffer;\n  }\n  return nullptr;\n}\n\nint w_av_format::get_io_ctx_size() const {\n  if (this->_io_ctx) {\n    return this->_io_ctx->buffer_size;\n  }\n  return -1;\n}\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_av_format.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_FFMPEG\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n\nextern \"C\" {\n#include <libavformat/avformat.h>\n}\n\nnamespace wolf::media::ffmpeg {\nclass w_av_format {\n public:\n#pragma region Constructors /Destructor\n  W_API w_av_format() noexcept;\n  W_API ~w_av_format() noexcept { _release(); };\n  // move constructor.\n  W_API w_av_format(w_av_format &&p_other) noexcept = default;\n  // move assignment operator.\n  W_API w_av_format &operator=(w_av_format &&p_other) noexcept = default;\n#pragma endregion\n\n  boost::leaf::result<int> init(_In_ int p_stream_buf_size = 32'767) noexcept;\n\n  uint8_t *get_io_ctx_buffer() const;\n  int get_io_ctx_size() const;\n\n  std::function<int(_Inout_ uint8_t * /*p_buf*/, _In_ int /*p_buf_size*/)> on_read_callback;\n\n private:\n  // copy constructor.\n  w_av_format(const w_av_format &) = delete;\n  // copy assignment operator.\n  w_av_format &operator=(const w_av_format &) = delete;\n\n  // release\n  void _release() noexcept;\n\n  std::unique_ptr<uint8_t[]> _stream_buffer = nullptr;\n  std::unique_ptr<AVFormatContext> _fmt_ctx = nullptr;\n  std::unique_ptr<AVIOContext> _io_ctx = nullptr;\n};\n}  // namespace wolf::media::ffmpeg\n\n#endif // WOLF_MEDIA_FFMPEG\n"
  },
  {
    "path": "wolf/media/ffmpeg/w_av_frame.cpp",
    "content": "#ifdef WOLF_MEDIA_FFMPEG\n\n#include \"w_av_frame.hpp\"\n#include \"w_ffmpeg_ctx.hpp\"\n\nextern \"C\" {\n#include <libavutil/imgutils.h>\n#include <libswscale/swscale.h>\n#include <libswresample/swresample.h>\n}\n\n#ifdef WOLF_MEDIA_STB\n#include <stb_image.h>\n#include <stb_image_write.h>\n#endif //WOLF_MEDIA_STB\n\nusing w_av_frame = wolf::media::ffmpeg::w_av_frame;\nusing w_av_config = wolf::media::ffmpeg::w_av_config;\n\nw_av_frame::w_av_frame(_In_ w_av_config &&p_config) noexcept : _config(std::move(p_config)) {}\n\nvoid w_av_frame::_release() noexcept {\n  if (this->_av_frame != nullptr) {\n    av_frame_free(&this->_av_frame);\n    if (this->_config.nb_channels > 0) {\n      av_channel_layout_uninit(&this->_av_frame->ch_layout);\n    }\n  }\n}\n\nvoid w_av_frame::_move(w_av_frame &&p_other) noexcept {\n  if (this == &p_other) {\n    return;\n  }\n  this->_av_frame = std::exchange(p_other._av_frame, nullptr);\n  this->_config = std::move(p_other._config);\n  this->_data = std::move(p_other._data);\n}\n\nboost::leaf::result<int> w_av_frame::init() noexcept {\n  _release();\n\n  // allocate memory for AVFrame\n  this->_av_frame = av_frame_alloc();\n  if (this->_av_frame == nullptr) {\n    return W_FAILURE(std::errc::not_enough_memory, \"could not allocate memory for AVFrame\");\n  }\n\n  // set audio\n  this->_av_frame->sample_rate = this->_config.sample_rate;\n  if (this->_config.nb_channels > 0) {\n    av_channel_layout_default(&this->_av_frame->ch_layout, this->_config.nb_channels);\n  }\n\n  // set video\n  this->_av_frame->format = gsl::narrow_cast<int>(this->_config.format);\n  this->_av_frame->width = this->_config.width;\n  this->_av_frame->height = this->_config.height;\n\n  return 0;\n}\n\nboost::leaf::result<int> w_av_frame::set_video_frame(\n    _Inout_ std::vector<uint8_t> &&p_data) noexcept {\n  const auto _width = this->_config.width;\n  const auto _height = this->_config.height;\n  const auto _alignment = this->_config.alignment;\n\n  // check for width and height\n  if (_width <= 0 || _height <= 0) {\n    return W_FAILURE(std::errc::invalid_argument, \"width or height of w_av_frame is zero\");\n  }\n\n  // move the owenership of data to buffer\n  this->_data = std::forward<std::vector<uint8_t> &&>(p_data);\n\n  const auto _buffer_size = this->_config.get_required_video_buffer_size();\n  if (this->_data.empty()) {\n    this->_data.resize(_buffer_size, 0);\n  }\n\n  // if size does not fit\n  if (this->_data.size() != _buffer_size) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     wolf::format(\"w_av_frame video buffer size is expected {} but is {}\",\n                                  _buffer_size, this->_data.size()));\n  }\n\n  const auto _ret = av_image_fill_arrays(this->_av_frame->data, this->_av_frame->linesize,\n                                         gsl::narrow_cast<const uint8_t *>(this->_data.data()),\n                                         this->_config.format, this->_av_frame->width,\n                                         this->_av_frame->height, _alignment);\n  if (_ret < 0) {\n    return W_FAILURE(std::errc::operation_canceled, \"av_image_fill_arrays failed\");\n  }\n  return _ret;\n}\n  \nvoid w_av_frame::set_pts(_In_ int64_t p_pts) noexcept { this->_av_frame->pts = p_pts; }\n\nstd::tuple<uint8_t **, int> w_av_frame::get() const noexcept {\n  if (this->_av_frame) {\n    auto _buffer_size =\n        av_image_get_buffer_size(gsl::narrow_cast<AVPixelFormat>(this->_av_frame->format),\n                                 this->_av_frame->width, this->_av_frame->height, 4);\n\n    return std::make_tuple(this->_av_frame->data, _buffer_size);\n  }\n  return std::make_tuple(nullptr, 0);\n}\n\nw_av_config w_av_frame::get_config() const noexcept { return this->_config; }\n\nboost::leaf::result<w_av_frame> w_av_frame::convert_audio(_In_ w_av_config &&p_dst_config) {\n  auto _ret = 0;\n\n  SwrContext *swr = nullptr;\n  auto _dst_frame = w_av_frame(std::move(p_dst_config));\n  _dst_frame.init();\n\n  DEFER {\n    if (_ret != S_OK) {\n      if (swr) {\n        if (swr_is_initialized(swr)) {\n          swr_close(swr);\n        }\n        swr_free(&swr);\n      }\n    }\n  });\n\n  swr_alloc_set_opts2(&swr, &this->_channel_layout, p_dst_config.sample_fmts,\n                      p_dst_config.sample_rate, &this->_av_frame->ch_layout,\n                      gsl::narrow_cast<AVSampleFormat>(this->_av_frame->format),\n                      this->_av_frame->sample_rate, 0, nullptr);\n\n  if (swr == nullptr) {\n    _ret = -1;\n    return W_FAILURE(std::errc::operation_canceled, \"could not create audio SwrContext\");\n  }\n\n  _ret = swr_init(swr);\n\n  if (_ret < 0) {\n    return W_FAILURE(std::errc::operation_canceled, \"could not initialize audio SwrContext\");\n  }\n\n  // get number of samples\n  auto _sample_rate = gsl::narrow_cast<int64_t>(this->_av_frame->sample_rate);\n\n  auto _delay = swr_get_delay(swr, _sample_rate);\n\n  const auto _rescale_rnd =\n      av_rescale_rnd(_delay + _sample_rate, gsl::narrow_cast<int64_t>(p_dst_config.sample_rate),\n                     _sample_rate, AV_ROUND_UP);\n\n  _dst_frame._av_frame->nb_samples = gsl::narrow_cast<int>(_rescale_rnd);\n\n  auto size = av_samples_alloc(gsl::narrow_cast<uint8_t **>(&_dst_frame._av_frame->data[0]),\n                               &_dst_frame._av_frame->linesize[0],\n                               this->_channel_layout.nb_channels, _dst_frame._config.nb_channels,\n                               gsl::narrow_cast<AVSampleFormat>(p_dst_config.sample_fmts), 1);\n\n  if (size < 0) {\n    _ret = -1;\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"could not allocate memory for buffer of audio\");\n  }\n\n  /* convert to destination format */\n  size = swr_convert(swr, gsl::narrow_cast<uint8_t **>(&_dst_frame._av_frame->data[0]),\n                     _dst_frame._av_frame->nb_samples,\n                     (const uint8_t **)(&this->_av_frame->data[0]), this->_av_frame->nb_samples);\n\n  if (size < 0) {\n    _ret = -1;\n    return W_FAILURE(std::errc::operation_canceled, \"error while audio converting\\n\");\n  }\n\n  const auto _buffer_size = av_samples_get_buffer_size(&_dst_frame._av_frame->linesize[0],\n                                                       _dst_frame._av_frame->ch_layout.nb_channels,\n                                                       size, p_dst_config.sample_fmts, 1);\n\n  if (_buffer_size < 0) {\n    _ret = -1;\n    return W_FAILURE(std::errc::operation_canceled, \"could not get sample buffer size\\n\");\n  }\n\n  return _dst_frame;\n}\n\nboost::leaf::result<w_av_frame> w_av_frame::convert_video(_In_ w_av_config &&p_dst_config) {\n  // create a buffer and dst frame\n  auto _video_buffer = std::vector<uint8_t>();\n  auto _dst_frame = w_av_frame(std::move(p_dst_config));\n  BOOST_LEAF_CHECK(_dst_frame.init());\n  BOOST_LEAF_CHECK(_dst_frame.set_video_frame(std::move(_video_buffer)));\n\n  auto *_context = sws_getContext(\n      this->_config.width, this->_config.height, this->_config.format, _dst_frame._config.width,\n      _dst_frame._config.height, _dst_frame._config.format, SWS_BICUBIC, nullptr, nullptr, nullptr);\n  if (_context == nullptr) {\n    return W_FAILURE(std::errc::not_enough_memory, \"could not create sws context\");\n  }\n\n  auto _dst_frame_nn = gsl::not_null<AVFrame *>(_dst_frame._av_frame);\n  const auto _height =\n      sws_scale(_context, gsl::narrow_cast<const uint8_t *const *>(this->_av_frame->data),\n                gsl::narrow_cast<const int *>(this->_av_frame->linesize), 0, this->_config.height,\n                gsl::narrow_cast<uint8_t *const *>(_dst_frame_nn->data),\n                gsl::narrow_cast<const int *>(_dst_frame_nn->linesize));\n\n  // free context\n  sws_freeContext(_context);\n\n  if (_height < 0) {\n    return W_FAILURE(\n        std::errc::invalid_argument,\n        \"w_av_frame sws_scale failed because: \\\"\" + w_ffmpeg_ctx::get_av_error_str(_height) + \"\\\"\");\n  }\n\n  return _dst_frame;\n}\n\nboost::leaf::result<w_av_frame> w_av_frame::load_video_frame_from_img_file(\n    _In_ const std::filesystem::path &p_path, _In_ AVPixelFormat p_pixel_fmt) {\n#ifdef WOLF_MEDIA_STB\n\n  // width, height, comp\n  int _width = 0;\n  int _height = 0;\n  int _comp = 0;\n\n  const auto _path = p_path.string();\n  if (!std::filesystem::exists(p_path)) {\n    return W_FAILURE(std::errc::invalid_argument, \" path not exist for av_frame\" + _path);\n  }\n\n  auto *_raw_img_data = stbi_load(_path.c_str(), &_width, &_height, &_comp, 0);\n\n  if (_raw_img_data == nullptr) {\n    return W_FAILURE(std::errc::invalid_argument, \"could not load image file \" + _path);\n  }\n\n  auto _len = gsl::narrow_cast<size_t>(_width * _height * _comp);\n  const auto _raw_img_data_span = gsl::span(_raw_img_data, _raw_img_data + _len);\n  auto _raw_img_data_vec =\n      std::vector<uint8_t>(_raw_img_data_span.begin(), _raw_img_data_span.end());\n\n  free(_raw_img_data);\n\n  auto _src_config = w_av_config(p_pixel_fmt, _width, _height);\n  // create an av_frame from image raw data\n  auto _src_frame = w_av_frame(std::move(_src_config));\n  BOOST_LEAF_CHECK(_src_frame.init());\n  BOOST_LEAF_CHECK(_src_frame.set_video_frame(std::move(_raw_img_data_vec)));\n\n  return _src_frame;\n#else\n  return W_FAILURE(std::errc::not_supported, \"WOLF_MEDIA_STB not defined\");\n#endif\n}\n\nboost::leaf::result<int> w_av_frame::save_video_frame_to_img_file(\n    _In_ const std::filesystem::path &p_path, int p_quality) noexcept {\n  try {\n#ifdef WOLF_MEDIA_STB\n\n    if (this->_av_frame == nullptr || this->_av_frame->width == 0 || this->_av_frame->height == 0) {\n      return W_FAILURE(std::errc::invalid_argument, \"bad parameters for avframe\");\n    }\n\n    const auto _path = p_path.string();\n    auto _ext = p_path.extension().string();\n    std::transform(_ext.cbegin(), _ext.cend(), _ext.begin(), ::tolower);\n\n    const auto _comp = this->_av_frame->linesize[0] / this->_av_frame->width;\n    if (_ext == \".bmp\") {\n      return stbi_write_bmp(_path.c_str(), this->_config.width, this->_config.height, _comp,\n                            this->_av_frame->data[0]);\n    }\n    if (_ext == \".png\") {\n      return stbi_write_png(_path.c_str(), this->_config.width, this->_config.height, _comp,\n                            this->_av_frame->data[0], this->_av_frame->linesize[0]);\n    }\n    if (_ext == \".jpg\" || _ext == \".jpeg\") {\n      return stbi_write_jpg(_path.c_str(), this->_config.width, this->_config.height, _comp,\n                            this->_av_frame->data[0], p_quality);\n    }\n    return W_FAILURE(std::errc::invalid_argument, \"image format not supported for \" + _path);\n  } catch (const std::exception &p_exc) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"caught an esxception for \" + std::string(p_exc.what()));\n  }\n#else\n    return W_FAILURE(std::errc::not_supported, \"WOLF_MEDIA_STB not defined\");\n#endif\n}\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_av_frame.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_FFMPEG\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n#include \"w_av_config.hpp\"\n\nextern \"C\" {\n#include <libavformat/avformat.h>\n}\n\nnamespace wolf::media::ffmpeg {\n\nclass w_decoder;\nclass w_encoder;\n\nclass w_av_frame {\n  friend w_decoder;\n  friend w_encoder;\n\n public:\n  /**\n   * constructor the av_frame with specific config\n   * @param p_config, the av audio config\n   */\n  W_API explicit w_av_frame(_In_ w_av_config &&p_config) noexcept;\n\n  // destructor\n  W_API virtual ~w_av_frame() noexcept { _release(); }\n\n  // move constructor.\n  W_API w_av_frame(w_av_frame &&p_other) noexcept { _move(std::forward<w_av_frame &&>(p_other)); }\n  // move assignment operator.\n  W_API w_av_frame &operator=(w_av_frame &&p_other) noexcept {\n    _move(std::forward<w_av_frame &&>(p_other));\n    return *this;\n  }\n\n  /**\n   * initialize the avframe\n   * @returns zero on success\n   */\n  W_API\n  boost::leaf::result<int> init() noexcept;\n\n  /**\n   * set the AVFrame data\n   * @param p_data, the initial data of ffmpeg AVFrame\n   * @param p_alignment, the alignment\n   * @returns zero on success\n   */\n  W_API boost::leaf::result<int> set_video_frame(_Inout_ std::vector<uint8_t> &&p_data) noexcept;\n\n  /**\n   * set the AVFrame's pts\n   * @param p_pts, the pts data\n   * @returns void\n   */\n  W_API void set_pts(_In_ int64_t p_pts) noexcept;\n\n  /**\n   * get data and linesize as a tuple\n   * @returns tuple<int*[8], int[8]>\n   */\n  W_API\n  std::tuple<uint8_t **, int> get() const noexcept;\n\n  /**\n   * convert the ffmpeg video AVFrame\n   * @returns the converted instance of AVFrame\n   */\n  W_API\n  boost::leaf::result<w_av_frame> convert_video(_In_ w_av_config &&p_dst_config);\n\n  /**\n   * convert the ffmpeg audio AVFrame\n   * @returns the converted instance of AVFrame\n   */\n  W_API\n  boost::leaf::result<w_av_frame> convert_audio(_In_ w_av_config &&p_dst_config);\n\n  /**\n   * @returns config\n   */\n  W_API w_av_config get_config() const noexcept;\n\n#ifdef WOLF_MEDIA_STB\n\n  /**\n   * create w_av_frame from image file path\n   * @returns the AVFrame\n   */\n  W_API\n  static boost::leaf::result<w_av_frame> load_video_frame_from_img_file(\n      _In_ const std::filesystem::path &p_path, _In_ AVPixelFormat p_pixel_fmt);\n\n  /**\n   * save to to the image file\n   * @param p_quality, quality will be used only for jpeg and is between 1 and\n   * 100\n   * @returns zero on success\n   */\n  W_API\n  boost::leaf::result<int> save_video_frame_to_img_file(_In_ const std::filesystem::path &p_path,\n                                                        int p_quality = 100) noexcept;\n\n#endif\n\n private:\n  // copy constructor.\n  w_av_frame(const w_av_frame &) = delete;\n  // copy assignment operator.\n  w_av_frame &operator=(const w_av_frame &) = delete;\n\n  // release\n  void _release() noexcept;\n  // move\n  void _move(w_av_frame &&p_other) noexcept;\n\n  // the channel layout of the audio\n  AVChannelLayout _channel_layout = {};\n  // the AVFrame config\n  w_av_config _config = {};\n  // the ffmpeg AVFrame\n  gsl::owner<AVFrame *> _av_frame = nullptr;\n  // the ffmpeg AVFrame data\n  std::vector<uint8_t> _data = {};\n};\n}  // namespace wolf::media::ffmpeg\n\n#endif // WOLF_MEDIA_FFMPEG\n"
  },
  {
    "path": "wolf/media/ffmpeg/w_av_packet.cpp",
    "content": "#ifdef WOLF_MEDIA_FFMPEG\n\n#include \"w_av_packet.hpp\"\n\nusing w_av_packet = wolf::media::ffmpeg::w_av_packet;\n\nw_av_packet::w_av_packet(_In_ AVPacket *p_av_packet) noexcept\n    : _packet(p_av_packet) {}\n\nboost::leaf::result<int> w_av_packet::init() noexcept {\n  _release();\n  return init(nullptr, 0);\n}\n\nboost::leaf::result<int> w_av_packet::init(_Inout_ std::vector<uint8_t> &&p_data) noexcept {\n  _release();\n  this->_own_data = std::forward<std::vector<uint8_t> &&>(p_data);\n  return init(this->_own_data.data(), this->_own_data.size());\n}\n\nboost::leaf::result<int> w_av_packet::init(_In_ uint8_t *p_data, _In_ size_t p_data_len) noexcept {\n\n  this->_packet = av_packet_alloc();\n  if (this->_packet == nullptr) {\n    return W_FAILURE(std::errc::not_enough_memory, \"could not allocate memory for av packet\");\n  }\n  if (p_data && p_data_len) {\n    this->_packet->data = p_data;\n    this->_packet->size = gsl::narrow_cast<int>(p_data_len);\n  }\n\n  return 0;\n}\n\nvoid w_av_packet::unref() noexcept { av_packet_unref(this->_packet); }\n\nuint8_t *w_av_packet::get_data() const noexcept {\n  return this->_packet->data;\n}\n\nint w_av_packet::get_size() const noexcept {\n  return this->_packet->size;\n}\n\nint w_av_packet::get_stream_index() const noexcept {\n  return this->_packet->stream_index;\n}\n\nvoid w_av_packet::_release() noexcept {\n  if (this->_packet != nullptr) {\n    av_packet_free(&this->_packet);\n    this->_packet = nullptr;\n  }\n}\n\nvoid w_av_packet::_move(_Inout_ w_av_packet &&p_other) noexcept {\n  if (this == &p_other) {\n    return;\n  }\n  this->_packet = std::exchange(p_other._packet, nullptr);\n  this->_own_data = std::move(p_other._own_data);\n}\n\n#endif // WOLF_MEDIA_FFMPEG\n"
  },
  {
    "path": "wolf/media/ffmpeg/w_av_packet.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_FFMPEG\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n\nextern \"C\" {\n#include <libavcodec/packet.h>\n}\n\nnamespace wolf::media::ffmpeg {\n\nclass w_decoder;\nclass w_encoder;\nclass w_ffmpeg;\n\nclass w_av_packet {\n  friend w_decoder;\n  friend w_encoder;\n  friend w_ffmpeg;\n\n public:\n  // default construct an av_packet\n  W_API w_av_packet() noexcept = default;\n\n  /**\n   * construct an av_packet\n   */\n  W_API explicit w_av_packet(_In_ AVPacket *p_av_packet) noexcept;\n\n  // move constructor.\n  W_API w_av_packet(w_av_packet &&p_other) noexcept {\n    _move(std::forward<w_av_packet &&>(p_other));\n  }\n  // move assignment operator.\n  W_API w_av_packet &operator=(w_av_packet &&p_other) noexcept {\n    _move(std::forward<w_av_packet &&>(p_other));\n    return *this;\n  }\n\n  // destructor\n  W_API virtual ~w_av_packet() noexcept { _release(); }\n\n  /**\n   * initialize the av_packet\n   * @returns zero on success\n   */\n  W_API boost::leaf::result<int> init() noexcept;\n\n  /**\n   * initialize the av_packet from data\n   * @returns zero on success\n   */\n  W_API boost::leaf::result<int> init(_In_ uint8_t *p_data, _In_ size_t p_data_len) noexcept;\n\n  /**\n   * initialize the av_packet\n   * @returns void\n   */\n  W_API boost::leaf::result<int> init(_Inout_ std::vector<uint8_t> &&p_data) noexcept;\n\n  /**\n   * unref av_packet\n   */\n  W_API void unref() noexcept;\n\n  // get packet data\n  W_API uint8_t *get_data() const noexcept;\n\n  // get packet size\n  W_API int get_size() const noexcept;\n\n  // get stream index\n  W_API int get_stream_index() const noexcept;\n\n private:\n  // copy constructor.\n  w_av_packet(const w_av_packet &) = delete;\n  // copy assignment operator.\n  w_av_packet &operator=(const w_av_packet &) = delete;\n  // release the resources\n  void _release() noexcept;\n  // move the resources\n  void _move(_Inout_ w_av_packet && p_other) noexcept;\n\n  gsl::owner<AVPacket*> _packet = {};\n  std::vector<uint8_t> _own_data;\n};\n}  // namespace wolf::media::ffmpeg\n\n#endif"
  },
  {
    "path": "wolf/media/ffmpeg/w_decoder.cpp",
    "content": "﻿#ifdef WOLF_MEDIA_FFMPEG\n\n#include \"w_decoder.hpp\"\n\nusing w_decoder = wolf::media::ffmpeg::w_decoder;\n\nboost::leaf::result<int> w_decoder::decode_frame_from_packet(_In_ AVPacket *p_packet,\n                                                             _Inout_ w_av_frame &p_frame) {\n  // start decoding\n  auto _ret = avcodec_send_packet(this->ctx.codec_ctx, p_packet);\n  if (_ret < 0) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"could not parse packet for decoding because:\\\"\" +\n                         w_ffmpeg_ctx::get_av_error_str(_ret) + \"\\\"\");\n  }\n\n  for (;;) {\n    _ret = avcodec_receive_frame(this->ctx.codec_ctx, p_frame._av_frame);\n    if (_ret == 0 || _ret == AVERROR(EAGAIN) || _ret == AVERROR_EOF) {\n      break;\n    }\n    if (_ret < 0) {\n      return W_FAILURE(std::errc::operation_canceled,\n                       \"error happened during the encoding because:\\\"\" +\n                           w_ffmpeg_ctx::get_av_error_str(_ret) + \"\\\"\");\n    }\n  }\n  return 0;\n}\n\nboost::leaf::result<int> w_decoder::decode(_In_ const w_av_packet &p_packet,\n                                           _Inout_ w_av_frame &p_frame,\n                                           _In_ bool p_flush) noexcept {\n  auto _dst_packet = w_av_packet();\n  _dst_packet.init();\n\n  for (;;) {\n    const auto _bytes =\n        av_parser_parse2(this->ctx.parser, this->ctx.codec_ctx, &_dst_packet._packet->data,\n                         &_dst_packet._packet->size, p_packet._packet->data, p_packet._packet->size,\n                         AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);\n\n    if (_bytes == 0) {\n      break;\n    }\n\n    if (_dst_packet._packet->size == 0) {\n      // try decode the inputed packet\n      BOOST_LEAF_CHECK(decode_frame_from_packet(p_packet._packet, p_frame));\n    } else {\n      if (_bytes < 0) {\n        return W_FAILURE(std::errc::operation_canceled, \"could not parse packet for decoding\");\n      }\n      p_packet._packet->data += _bytes;\n      p_packet._packet->size -= _bytes;\n      if (_dst_packet._packet->size > 0) {\n        BOOST_LEAF_CHECK(decode_frame_from_packet(_dst_packet._packet, p_frame));\n      }\n    }\n  }\n\n  if (p_flush) {\n    // flush the decoder\n    BOOST_LEAF_CHECK(decode_frame_from_packet(nullptr, p_frame));\n  }\n\n  return 0;\n}\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_decoder.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_FFMPEG\n\n#pragma once\n\n#include \"w_av_frame.hpp\"\n#include \"w_av_packet.hpp\"\n#include \"w_ffmpeg_ctx.hpp\"\n#include <variant>\n\nnamespace wolf::media::ffmpeg {\n\nclass w_decoder {\npublic:\n  w_ffmpeg_ctx ctx = {};\n\n  // constructor\n  W_API w_decoder() = default;\n  // destructor\n  W_API virtual ~w_decoder() noexcept = default;\n\n  // move constructor.\n  W_API w_decoder(w_decoder &&p_other) noexcept = default;\n  // move assignment operator.\n  W_API w_decoder &operator=(w_decoder &&p_other) noexcept = default;\n\n  W_API boost::leaf::result<int> decode(_In_ const w_av_packet &p_packet,\n                                        _Inout_ w_av_frame &p_frame,\n                                        _In_ bool p_flush = false) noexcept;\n\nprivate:\n  // copy constructor\n  w_decoder(const w_decoder &) = delete;\n  // copy operator\n  w_decoder &operator=(const w_decoder &) = delete;\n\n  boost::leaf::result<int> decode_frame_from_packet(_In_ AVPacket *p_packet,\n                                                    _Inout_ w_av_frame &p_frame);\n};\n} // namespace wolf::media::ffmpeg\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_encoder.cpp",
    "content": "﻿#ifdef WOLF_MEDIA_FFMPEG\n\n#include \"w_encoder.hpp\"\n\nusing w_encoder = wolf::media::ffmpeg::w_encoder;\nusing w_av_packet = wolf::media::ffmpeg::w_av_packet;\n\nboost::leaf::result<int> w_encoder::_encode_frame_to_packet(\n    _In_ const AVFrame *p_frame, _Inout_ std::vector<uint8_t> &p_packet_data) const noexcept {\n  auto _packet = w_av_packet();\n  _packet.init();\n\n  for (;;) {\n    auto _ret = avcodec_send_frame(this->ctx.codec_ctx, p_frame);\n    if (_ret < 0) {\n      return W_FAILURE(std::errc::operation_canceled,\n                       \"failed to send the avframe for encoding because:\\\"\" +\n                           w_ffmpeg_ctx::get_av_error_str(_ret) + \"\\\"\");\n    }\n\n    for (;;) {\n      _ret = avcodec_receive_packet(this->ctx.codec_ctx, _packet._packet);\n      if (_ret == 0 || _ret == AVERROR_EOF) {\n        if (_packet._packet->size) {\n          std::copy(_packet._packet->data, _packet._packet->data + _packet._packet->size,\n                    std::back_inserter(p_packet_data));\n        }\n        return 0;\n      }\n\n      _packet.unref();\n\n      if (_ret == AVERROR(EAGAIN)) {\n        break;\n      }\n      return W_FAILURE(std::errc::operation_canceled,\n                       \"error happened during the encoding because:\\\"\" +\n                           w_ffmpeg_ctx::get_av_error_str(_ret) + \"\\\"\");\n    }\n  }\n  return 0;\n}\n\nboost::leaf::result<int> w_encoder::encode(_In_ const w_av_frame &p_frame,\n                                           _Inout_ w_av_packet &p_packet,\n                                           _In_ bool p_flush) noexcept {\n  std::vector<uint8_t> _packet_data;\n\n  // encode frame to packet\n  BOOST_LEAF_CHECK(_encode_frame_to_packet(p_frame._av_frame, _packet_data));\n  if (p_flush) {\n    // flush\n    BOOST_LEAF_CHECK(_encode_frame_to_packet(nullptr, _packet_data));\n  }\n\n  // init packet\n  p_packet.init(std::move(_packet_data));\n\n  return {};\n}\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_encoder.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_FFMPEG\n\n#pragma once\n\n#include \"w_av_frame.hpp\"\n#include \"w_av_packet.hpp\"\n#include \"w_ffmpeg_ctx.hpp\"\n#include <variant>\n\nnamespace wolf::media::ffmpeg {\n\nclass w_encoder {\npublic:\n  // constructor\n  W_API w_encoder() = default;\n  // destructor\n  W_API virtual ~w_encoder() noexcept = default;\n\n  // move constructor.\n  W_API w_encoder(w_encoder &&p_other) noexcept = default;\n  // move assignment operator.\n  W_API w_encoder &operator=(w_encoder &&p_other) noexcept = default;\n\n  W_API boost::leaf::result<int> encode(_In_ const w_av_frame &p_frame,\n                                        _Inout_ w_av_packet &p_packet,\n                                        _In_ bool p_flush = true) noexcept;\n\n  w_ffmpeg_ctx ctx = {};\n\nprivate:\n  // copy constructor\n  w_encoder(const w_encoder &) = delete;\n  // copy operator\n  w_encoder &operator=(const w_encoder &) = delete;\n\n  boost::leaf::result<int>\n  _encode_frame_to_packet(_In_ const AVFrame *p_frame,\n          _Inout_ std::vector<uint8_t> &p_packet_data) const noexcept;\n};\n} // namespace wolf::media::ffmpeg\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_ffmpeg.cpp",
    "content": "﻿#ifdef WOLF_MEDIA_FFMPEG\n\n#include \"w_ffmpeg.hpp\"\n\nextern \"C\" {\n#include <libavutil/opt.h>\n}\n\nusing w_av_codec_opt = wolf::media::ffmpeg::w_av_codec_opt;\nusing w_av_config = wolf::media::ffmpeg::w_av_config;\nusing w_av_set_opt = wolf::media::ffmpeg::w_av_set_opt;\nusing w_decoder = wolf::media::ffmpeg::w_decoder;\nusing w_encoder = wolf::media::ffmpeg::w_encoder;\nusing w_ffmpeg = wolf::media::ffmpeg::w_ffmpeg;\nusing w_ffmpeg_ctx = wolf::media::ffmpeg::w_ffmpeg_ctx;\n\nstatic boost::leaf::result<AVDictionary *> s_set_dict(\n    _In_ const std::vector<w_av_set_opt> &p_opts) noexcept {\n  AVDictionary *_dict = nullptr;\n  if (p_opts.empty()) {\n    return _dict;\n  }\n\n  auto _ret = av_dict_set(&_dict, nullptr, nullptr, 0);\n  if (_ret < 0) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"could not allocate memory for AVDictionary because: \" +\n                         w_ffmpeg_ctx::get_av_error_str(_ret));\n  }\n\n  try {\n    for (const auto &_opt : p_opts) {\n      if (_opt.name.empty()) {\n        continue;\n      }\n\n      auto _name_str = _opt.name.c_str();\n      if (std::holds_alternative<int>(_opt.value)) {\n        // set an integer value\n        const auto _value = std::get<int>(_opt.value);\n        const auto _ret = av_dict_set_int(&_dict, _name_str, _value, 0);\n        if (_ret < 0) {\n          return W_FAILURE(std::errc::invalid_argument, \"could not set int value for \" + _opt.name +\n                                                            \":\" + std::to_string(_value) +\n                                                            \" because \" +\n                                                            w_ffmpeg_ctx::get_av_error_str(_ret));\n        }\n      } else {\n        // set string value\n        const auto _value_str = &std::get<std::string>(_opt.value);\n        if (_value_str && !_value_str->empty()) {\n          const auto _ret = av_dict_set(&_dict, _opt.name.c_str(), _value_str->c_str(), 0);\n          if (_ret < 0) {\n            return W_FAILURE(std::errc::invalid_argument,\n                             \"could not set string value for \" + _opt.name + \":\" + *_value_str +\n                                 \" because \" + w_ffmpeg_ctx::get_av_error_str(_ret));\n          }\n        }\n      }\n    }\n  } catch (const std::exception &p_exc) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"s_set_dict failed because: \" + std::string(p_exc.what()));\n  }\n  return _dict;\n}\n\nstatic boost::leaf::result<int> s_create(_Inout_ w_ffmpeg_ctx &p_ctx,\n                                         _In_ const w_av_config &p_config,\n                                         _In_ const w_av_codec_opt &p_codec_opts,\n                                         _In_ const std::vector<w_av_set_opt> &p_opts) noexcept {\n  p_ctx.codec_ctx = avcodec_alloc_context3(p_ctx.codec);\n  if (p_ctx.codec_ctx == nullptr) {\n    return W_FAILURE(std::errc::not_enough_memory,\n                     \"could not allocate memory for avcodec context3\");\n  }\n\n  bool _has_error = false;\n  DEFER {\n    if (_has_error && p_ctx.codec_ctx) {\n      auto _ptr = p_ctx.codec_ctx;\n      avcodec_free_context(&_ptr);\n      p_ctx.codec_ctx = nullptr;\n    }\n  });\n\n  p_ctx.codec_ctx->width = p_config.width;\n  p_ctx.codec_ctx->height = p_config.height;\n  p_ctx.codec_ctx->bit_rate = p_codec_opts.bitrate;\n  p_ctx.codec_ctx->time_base = AVRational{1, p_codec_opts.fps};\n  p_ctx.codec_ctx->framerate = AVRational{p_codec_opts.fps, 1};\n  p_ctx.codec_ctx->pix_fmt = p_config.format;\n\n  // set gop\n  if (p_codec_opts.gop >= 0) {\n    p_ctx.codec_ctx->gop_size = p_codec_opts.gop;\n  }\n  // set refs\n  if (p_codec_opts.refs >= 0) {\n    p_ctx.codec_ctx->refs = p_codec_opts.refs;\n  }\n  // set frames\n  if (p_codec_opts.max_b_frames >= 0) {\n    p_ctx.codec_ctx->max_b_frames = p_codec_opts.max_b_frames;\n  }\n  // set thread numbers\n  if (p_codec_opts.thread_count >= 0) {\n    p_ctx.codec_ctx->thread_count = p_codec_opts.thread_count;\n  }\n  // set level\n  if (p_codec_opts.level >= 0) {\n    p_ctx.codec_ctx->level = p_codec_opts.level;\n  }\n  // set flags\n  if (p_ctx.codec_ctx->flags & AVFMT_GLOBALHEADER) {\n    p_ctx.codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;\n  }\n\n  try {\n    for (const auto &_opt : p_opts) {\n      if (_opt.name.empty()) {\n        continue;\n      }\n\n      auto _name_str = _opt.name.c_str();\n      if (std::holds_alternative<int>(_opt.value)) {\n        // set an integer value\n        const auto _value = std::get<int>(_opt.value);\n        const auto _ret = av_opt_set_int(p_ctx.codec_ctx->priv_data, _name_str, _value, 0);\n        if (_ret < 0) {\n          return W_FAILURE(std::errc::invalid_argument, \"could not set int value for \" + _opt.name +\n                                                            \":\" + std::to_string(_value) +\n                                                            \" because \" +\n                                                            w_ffmpeg_ctx::get_av_error_str(_ret));\n        }\n      } else if (std::holds_alternative<double>(_opt.value)) {\n        // set double value\n        const auto _value = std::get<int>(_opt.value);\n        const auto _ret = av_opt_set_double(p_ctx.codec_ctx->priv_data, _name_str, _value, 0);\n        if (_ret < 0) {\n          return W_FAILURE(std::errc::invalid_argument, \"could not set double value for \" +\n                                                            _opt.name + \":\" +\n                                                            std::to_string(_value) + \" because \" +\n                                                            w_ffmpeg_ctx::get_av_error_str(_ret));\n        }\n      } else {\n        // set string value\n        const auto _value_str = &std::get<std::string>(_opt.value);\n        if (_value_str && !_value_str->empty()) {\n          const auto _ret =\n              av_opt_set(p_ctx.codec_ctx->priv_data, _opt.name.c_str(), _value_str->c_str(), 0);\n          if (_ret < 0) {\n            return W_FAILURE(std::errc::invalid_argument,\n                             \"could not set string value for \" + _opt.name + \":\" + *_value_str +\n                                 \" because \" + w_ffmpeg_ctx::get_av_error_str(_ret));\n          }\n        }\n      }\n    }\n  } catch (const std::exception &p_exc) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"could not set av option because: \" + std::string(p_exc.what()));\n  }\n\n  // open avcodec\n  const auto _ret = avcodec_open2(p_ctx.codec_ctx, p_ctx.codec_ctx->codec, nullptr);\n  if (_ret < 0) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"could not open avcodec because \" + w_ffmpeg_ctx::get_av_error_str(_ret));\n  }\n  return 0;\n}\n\nboost::leaf::result<w_encoder> w_ffmpeg::create_encoder(\n    _In_ const w_av_config &p_config, _In_ AVCodecID p_id, _In_ const w_av_codec_opt &p_codec_opts,\n    _In_ const std::vector<w_av_set_opt> &p_opts) noexcept {\n  w_encoder _encoder = {};\n\n  _encoder.ctx.codec = avcodec_find_encoder(p_id);\n  if (_encoder.ctx.codec == nullptr) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"could not find encoder codec id: \" + std::to_string(p_id));\n  }\n\n  BOOST_LEAF_CHECK(s_create(_encoder.ctx, p_config, p_codec_opts, p_opts));\n\n  return _encoder;\n}\n\nboost::leaf::result<w_encoder> w_ffmpeg::create_encoder(\n    _In_ const w_av_config &p_config, _In_ const std::string &p_id,\n    _In_ const w_av_codec_opt &p_codec_opts,\n    _In_ const std::vector<w_av_set_opt> &p_opts) noexcept {\n  w_encoder _encoder = {};\n\n _encoder.ctx.codec = avcodec_find_encoder_by_name(p_id.c_str());\n  if (_encoder.ctx.codec == nullptr) {\n    return W_FAILURE(std::errc::invalid_argument, \"could not find encoder codec id: \" + p_id);\n  };\n\n  BOOST_LEAF_CHECK(s_create(_encoder.ctx, p_config, p_codec_opts, p_opts));\n\n  return _encoder;\n}\n\nboost::leaf::result<w_decoder> w_ffmpeg::create_decoder(\n    _In_ const w_av_config &p_config, _In_ const AVCodecID p_id,\n    _In_ const w_av_codec_opt &p_codec_opts,\n    _In_ const std::vector<w_av_set_opt> &p_opts) noexcept {\n  w_decoder _decoder = {};\n\n  _decoder.ctx.codec = avcodec_find_decoder(p_id);\n  if (_decoder.ctx.codec == nullptr) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"could not find decoder codec id: \" + std::to_string(p_id));\n  }\n\n  _decoder.ctx.parser = av_parser_init(_decoder.ctx.codec->id);\n  if (_decoder.ctx.parser == nullptr) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"could not initialize parser for codec id: \" + std::to_string(p_id));\n  }\n\n  BOOST_LEAF_CHECK(s_create(_decoder.ctx, p_config, p_codec_opts, p_opts));\n\n  return _decoder;\n}\n\nboost::leaf::result<w_decoder> w_ffmpeg::create_decoder(\n    _In_ const w_av_config &p_config, _In_ const std::string &p_id,\n    _In_ const w_av_codec_opt &p_codec_opts,\n    _In_ const std::vector<w_av_set_opt> &p_opts) noexcept {\n  w_decoder _decoder = {};\n\n  _decoder.ctx.codec = avcodec_find_decoder_by_name(p_id.c_str());\n  if (_decoder.ctx.codec == nullptr) {\n    return W_FAILURE(std::errc::invalid_argument, \"could not find decoder codec id: \" + p_id);\n  }\n\n  _decoder.ctx.parser = av_parser_init(_decoder.ctx.codec->id);\n  if (_decoder.ctx.parser == nullptr) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"could not initialize parser for codec id: \" + p_id);\n  }\n  \n  BOOST_LEAF_CHECK(s_create(_decoder.ctx, p_config, p_codec_opts, p_opts));\n\n  return _decoder;\n}\n\nboost::leaf::result<int> w_ffmpeg::open_stream(\n    _In_ const std::string &p_url, _In_ const std::vector<w_av_set_opt> &p_opts,\n    _In_ const\n        std::function<bool(const w_av_packet & /*p_packet*/, const AVStream * /*p_audio_stream*/,\n                           const AVStream * /*p_video_stream*/)> &p_on_frame) noexcept {\n  try {\n    // url is invalid\n    if (p_url.empty()) {\n      return W_FAILURE(std::errc::invalid_argument,\n                       \"could not allocate memory for av format context\");\n    }\n\n    // allocate memory for avformat context\n    auto _fmt_ctx = avformat_alloc_context();\n    if (_fmt_ctx == nullptr) {\n      return W_FAILURE(std::errc::not_enough_memory,\n                       \"could not allocate memory for av format context from the url: \" + p_url);\n    }\n\n    DEFER {\n      if (_fmt_ctx != nullptr) {\n        // free av format context\n        avformat_free_context(_fmt_ctx);\n        _fmt_ctx = nullptr;\n      }\n    });\n\n    // allocate memory for packet\n    auto _packet = w_av_packet();\n    BOOST_LEAF_CHECK(_packet.init());\n\n    // set options to av format context\n    BOOST_LEAF_AUTO(_dict, s_set_dict(p_opts));\n\n    // open input url\n    int _ret = avformat_open_input(&_fmt_ctx, p_url.c_str(), nullptr, &_dict);\n    if (_ret < 0) {\n      return W_FAILURE(std::errc::operation_canceled,\n                       \"could not open input url: \" + p_url +\n                           \" because: \" + w_ffmpeg_ctx::get_av_error_str(_ret));\n    }\n\n    // find the stream info\n    _ret = avformat_find_stream_info(_fmt_ctx, nullptr);\n    if (_ret < 0) {\n      return W_FAILURE(std::errc::operation_canceled,\n                       \"could not find stream info from the url: \" + p_url);\n    }\n\n    if (_fmt_ctx->nb_streams == 0) {\n      return W_FAILURE(std::errc::operation_canceled, \"missing stream for the url: \" + p_url);\n    }\n\n    // search for audio & video stream\n    const auto _video_stream_index =\n        av_find_best_stream(_fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);\n    const auto _audio_stream_index =\n        av_find_best_stream(_fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);\n\n    if (_audio_stream_index < 0 && _video_stream_index < 0) {\n      return W_FAILURE(std::errc::operation_canceled,\n                       \"could not find any video or audio stream from the url: \" + p_url);\n    }\n\n    AVStream *_audio_stream = nullptr;\n    AVStream *_video_stream = nullptr;\n\n    if (_audio_stream_index >= 0) {\n      _audio_stream = _fmt_ctx->streams[_audio_stream_index];\n    }\n    if (_video_stream_index >= 0) {\n      _video_stream = _fmt_ctx->streams[_video_stream_index];\n    }\n\n    for (;;) {\n      // unref packet\n      _packet.unref();\n      // read packet\n      _ret = av_read_frame(_fmt_ctx, _packet._packet);\n      if (_ret < 0) {\n        break;\n      }\n\n      if (p_on_frame && !p_on_frame(_packet, _audio_stream, _video_stream)) {\n        break;\n      }\n    }\n    return 0;\n  } catch (const std::exception &p_exc) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"caught an exception: \" + std::string(p_exc.what()));\n  }\n}\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_ffmpeg.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_FFMPEG\n\n#pragma once\n\n#include \"w_av_packet.hpp\"\n#include \"w_ffmpeg_ctx.hpp\"\n#include \"w_encoder.hpp\"\n#include \"w_decoder.hpp\"\n#include <variant>\n#include <functional>\n\nnamespace wolf::media::ffmpeg {\n\nstruct w_av_codec_opt {\n  int64_t bitrate;\n  int fps;\n  int gop;\n  int level;\n  int max_b_frames;\n  int refs;\n  int thread_count;\n};\n\nstruct w_av_set_opt {\n  // name of option\n  std::string name;\n  // value type\n  std::variant<int, double, std::string> value;\n};\n\nclass w_ffmpeg {\n public:\n  /*\n   * create ffmpeg encoder\n   * @param p_config, the video config\n   * @param p_id, the avcodec id\n   * @param p_codec_opts, the codec settings\n   * @param p_opts, the codec options\n   * @returns encoder object on success\n   */\n  W_API static boost::leaf::result<w_encoder> create_encoder(\n      _In_ const w_av_config &p_config, _In_ AVCodecID p_id,\n      _In_ const w_av_codec_opt &p_codec_opts,\n      _In_ const std::vector<w_av_set_opt> &p_opts = {}) noexcept;\n\n  /*\n   * create ffmpeg encoder\n   * @param p_config, the video config\n   * @param p_id, the avcodec id in string (e.g. \"libsvtav1\", \"libvpx\")\n   * @param p_codec_opts, the codec settings\n   * @param p_opts, the codec options\n   * @returns encoder object on success\n   */\n  W_API static boost::leaf::result<w_encoder> create_encoder(\n      _In_ const w_av_config &p_config, _In_ const std::string &p_id,\n      _In_ const w_av_codec_opt &p_codec_opts,\n      _In_ const std::vector<w_av_set_opt> &p_opts = {}) noexcept;\n\n  /*\n   * create ffmpeg decoder\n   * @param p_config, the avconfig\n   * @param p_id, the avcodec id in string (e.g. \"libsvtav1\", \"libvpx\")\n   * @param p_codec_opts, the codec options\n   * @param p_opts, the codec options\n   * @returns encoder object on success\n   */\n  W_API static boost::leaf::result<w_decoder> create_decoder(\n      _In_ const w_av_config &p_config, _In_ AVCodecID p_id,\n      _In_ const w_av_codec_opt &p_codec_opts,\n      _In_ const std::vector<w_av_set_opt> &p_opts = {}) noexcept;\n\n  /*\n   * create ffmpeg decoder\n   * @param p_config, the avconfig\n   * @param p_id, the avcodec id in string (e.g. \"libsvtav1\", \"libvpx\")\n   * @param p_codec_opts, the codec settings\n   * @param p_opts, the codec options\n   * @returns encoder object on success\n   */\n  W_API static boost::leaf::result<w_decoder> create_decoder(\n      _In_ const w_av_config &p_config, _In_ const std::string &p_id,\n      _In_ const w_av_codec_opt &p_codec_opts,\n      _In_ const std::vector<w_av_set_opt> &p_opts = {}) noexcept;\n\n  /*\n   * open and receive stream from file or url\n   * @param p_url, the url\n   * @param p_opts, the codec options\n   * @param p_on_frame, on frame data recieved callback\n   * @returns encoder object on success\n   */\n  W_API static boost::leaf::result<int> open_stream(\n      _In_ const std::string &p_url, _In_ const std::vector<w_av_set_opt> &p_opts,\n      _In_ const\n          std::function<bool(const w_av_packet & /*p_packet*/, const AVStream * /*p_audio_stream*/,\n                             const AVStream * /*p_video_stream*/)> &p_on_frame) noexcept;\n};\n}  // namespace wolf::media::ffmpeg\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_ffmpeg_ctx.cpp",
    "content": "﻿#ifdef WOLF_MEDIA_FFMPEG\n\n#include \"w_ffmpeg_ctx.hpp\"\n\nusing w_ffmpeg_ctx = wolf::media::ffmpeg::w_ffmpeg_ctx;\n\nvoid w_ffmpeg_ctx::_release() noexcept {\n  if (this->parser != nullptr) {\n    av_parser_close(this->parser);\n    this->parser = nullptr;\n  }\n  if (this->codec_ctx != nullptr) {\n    if (avcodec_is_open(this->codec_ctx) > 0) {\n      avcodec_close(this->codec_ctx);\n    }\n    avcodec_free_context(&this->codec_ctx);\n    this->codec_ctx = nullptr;\n  }\n}\n\nvoid w_ffmpeg_ctx::_move(w_ffmpeg_ctx &&p_other) noexcept {\n  if (this == &p_other) {\n    return;\n  }\n  this->codec_ctx = std::exchange(p_other.codec_ctx, nullptr);\n  this->codec = std::exchange(p_other.codec, nullptr);\n  this->parser = std::exchange(p_other.parser, nullptr);\n}\n\nstd::string w_ffmpeg_ctx::get_av_error_str(_In_ int p_error_code) noexcept {\n  std::array<char, W_MAX_PATH> _error[] = {'\\0'};\n  try {\n    std::ignore = av_make_error_string(_error->data(), W_MAX_PATH, p_error_code);\n    return std::string(_error->data());\n  } catch (...) {\n    return std::string();\n  }\n}\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/ffmpeg/w_ffmpeg_ctx.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_FFMPEG\n\n#pragma once\n\n#include <wolf.hpp>\n\nextern \"C\" {\n#include <libavcodec/avcodec.h>\n}\n\nnamespace wolf::media::ffmpeg {\n\nclass w_ffmpeg_ctx {\n public:\n  // constructor\n  W_API w_ffmpeg_ctx() = default;\n  // destructor\n  W_API virtual ~w_ffmpeg_ctx() noexcept { _release(); }\n\n  // move constructor.\n  W_API w_ffmpeg_ctx(w_ffmpeg_ctx &&p_other) noexcept {\n    _move(std::forward<w_ffmpeg_ctx &&>(p_other));\n  }\n  // move assignment operator.\n  W_API w_ffmpeg_ctx &operator=(w_ffmpeg_ctx &&p_other) noexcept {\n    _move(std::forward<w_ffmpeg_ctx &&>(p_other));\n    return *this;\n  }\n\n  W_API static std::string get_av_error_str(_In_ int p_error_code) noexcept;\n\n  gsl::owner<AVCodecContext*> codec_ctx = {};\n  gsl::owner<const AVCodec*> codec = {};\n  gsl::owner<AVCodecParserContext *> parser = {};\n\n private:\n  // copy constructor\n  w_ffmpeg_ctx(const w_ffmpeg_ctx &) = delete;\n  // copy operator\n  w_ffmpeg_ctx &operator=(const w_ffmpeg_ctx &) = delete;\n  // release all resources\n  void _release() noexcept;\n  // move all resources\n  void _move(w_ffmpeg_ctx &&p_other) noexcept;\n};\n}  // namespace wolf::media::ffmpeg\n\n#endif // WOLF_MEDIA_FFMPEG"
  },
  {
    "path": "wolf/media/gst/audio/w_audio_format.cpp",
    "content": "#include \"media/gst/audio/w_audio_format.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/audio/w_audio_format.hpp",
    "content": "#pragma once\n\n#include <gst/audio/audio-format.h>\n\nnamespace wolf::media::gst {\n\n/**\n * enum same as GstAudioFormat.\n */\nenum class w_audio_format\n{\n    Unknonw = GST_AUDIO_FORMAT_UNKNOWN,\n    Encoded = GST_AUDIO_FORMAT_ENCODED,\n\n    S8 = GST_AUDIO_FORMAT_S8,\n    S16 = GST_AUDIO_FORMAT_S16,\n    S16LE = GST_AUDIO_FORMAT_S16LE,\n    S16BE = GST_AUDIO_FORMAT_S16BE,\n    S32 = GST_AUDIO_FORMAT_S32,\n    S32LE = GST_AUDIO_FORMAT_S32LE,\n    S32BE = GST_AUDIO_FORMAT_S32BE,\n\n    U8 = GST_AUDIO_FORMAT_U8,\n    U16 = GST_AUDIO_FORMAT_U16,\n    U16LE = GST_AUDIO_FORMAT_U16LE,\n    U16BE = GST_AUDIO_FORMAT_U16BE,\n    U32 = GST_AUDIO_FORMAT_U32,\n    U32LE = GST_AUDIO_FORMAT_U32LE,\n    U32BE = GST_AUDIO_FORMAT_U32BE,\n\n    F32 = GST_AUDIO_FORMAT_F32,\n    F32LE = GST_AUDIO_FORMAT_F32LE,\n    F32BE = GST_AUDIO_FORMAT_F32BE,\n    F64 = GST_AUDIO_FORMAT_F32,\n    F64LE = GST_AUDIO_FORMAT_F64LE,\n    F64BE = GST_AUDIO_FORMAT_F64BE\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/audio/w_audio_info.cpp",
    "content": "#include \"media/gst/audio/w_audio_info.hpp\"\n\nnamespace wolf::media::gst {\n\nauto w_audio_info::make(w_audio_format p_format, size_t p_channels, size_t p_samples)\n    -> boost::leaf::result<w_audio_info>\n{\n    auto audioinfo_raw = gst_audio_info_new();\n    if (!audioinfo_raw) {\n        return W_FAILURE(std::errc::operation_canceled, \"couldn't create audio info.\");\n    }\n\n    auto format_raw = static_cast<GstAudioFormat>(p_format);\n    gst_audio_info_set_format(\n                audioinfo_raw,\n                format_raw,\n                gsl::narrow_cast<gint>(p_samples),\n                gsl::narrow_cast<gint>(p_channels),\n                nullptr\n                );\n\n    return w_audio_info(internal::w_raw_tag{}, audioinfo_raw);\n}\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/audio/w_audio_info.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include \"media/gst/internal/w_common.hpp\"\n#include \"media/gst/internal/w_wrapper.hpp\"\n#include \"media/gst/core/w_caps.hpp\"\n#include \"media/gst/audio/w_audio_format.hpp\"\n\n#include <gst/audio/audio-info.h>\n\n#include <stdexcept>\n#include <utility>\n\nnamespace wolf::media::gst {\n\n/**\n * wrapper of GstAudioInfo.\n */\nclass w_audio_info : public w_wrapper<w_audio_info, GstAudioInfo, void, gst_audio_info_free>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    /**\n     * @brief make a w_audio_info instance with given format and other info.\n     * @return a constructed audio info on success.\n     */\n    [[nodiscard]] static auto make(w_audio_format p_format,\n                                   std::size_t p_channels = 2,\n                                   std::size_t p_samples = 44100)\n        -> boost::leaf::result<w_audio_info>;\n\n    /**\n     * @brief make a w_caps with info values.\n     */\n    [[nodiscard]] w_caps to_caps()\n    {\n        auto caps_raw = gst_audio_info_to_caps(raw());\n        return internal::w_raw_access::from_raw<w_caps>(caps_raw);\n    }\n\n    /**\n     * @brief set sample rate.\n     * @param p_rate sample rate.\n     */\n    void set_rate(std::size_t p_rate)\n    {\n        raw()->rate = gsl::narrow_cast<gint>(p_rate);\n    }\n\n    /**\n     * @brief set channels.\n     */\n    void set_channels(std::size_t p_channels)\n    {\n        raw()->channels = gsl::narrow_cast<gint>(p_channels);\n    }\n\nprivate:\n    w_audio_info(internal::w_raw_tag, GstAudioInfo* p_rawptr) noexcept\n        : w_wrapper(p_rawptr)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_buffer.cpp",
    "content": "#include \"media/gst/core/w_buffer.hpp\"\n\n#include \"media/gst/internal/w_common.hpp\"\n\nnamespace wolf::media::gst {\n\nauto w_buffer::make(size_t p_size) -> boost::leaf::result<w_buffer>\n{\n    auto buffer_raw = gst_buffer_new_and_alloc(p_size);\n    if (!buffer_raw) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"couldn't create and allocate Buffer.\");\n    }\n\n    return w_buffer(internal::w_raw_tag{}, buffer_raw);\n}\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_buffer.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include \"media/gst/internal/w_wrapper.hpp\"\n\n#include <gst/gst.h>\n\n#include <cstddef>\n#include <stdexcept>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief read/write map flags.\n */\nenum class w_buffer_map_flags\n{\n    Read = GST_MAP_READ,\n    Write = GST_MAP_WRITE,\n    ReadWrite = GST_MAP_READWRITE\n};\n\nclass w_buffer;\n\n/**\n * helper class to map underlying data of w_buffer\n * to an accessible memory region and unmap on destruction.\n */\nclass w_buffer_mapped_data\n{\n    friend class w_buffer;\n\npublic:\n    w_buffer_mapped_data(const w_buffer_mapped_data&) = delete;\n    w_buffer_mapped_data(w_buffer_mapped_data&& p_other) noexcept\n        : _buffer(std::exchange(p_other._buffer, nullptr))\n        , _map(std::exchange(p_other._map, GstMapInfo{}))\n    {}\n\n    w_buffer_mapped_data& operator=(const w_buffer_mapped_data&) = delete;\n    w_buffer_mapped_data& operator=(w_buffer_mapped_data&& p_other) noexcept\n    {\n        std::swap(_buffer, p_other._buffer);\n        std::swap(_map, p_other._map);\n        return *this;\n    }\n\n    ~w_buffer_mapped_data() noexcept\n    {\n        if (_buffer) {\n            gst_buffer_unmap(_buffer, &_map);\n        }\n    }\n\n    [[nodiscard]] std::size_t size() const noexcept { return _map.size; }\n\n    [[nodiscard]] guint8* begin() noexcept { return _map.data; }\n    [[nodiscard]] const guint8* begin() const noexcept { return _map.data; }\n\n    [[nodiscard]] guint8* end() noexcept { return _map.data + _map.size; }\n    [[nodiscard]] const guint8* end() const noexcept { return _map.data + _map.size; }\n\n    [[nodiscard]] guint8* data() noexcept { return _map.data; }\n    [[nodiscard]] const guint8* data() const noexcept { return _map.data; }\n\n    [[nodiscard]] guint8& operator[](std::size_t p_index) { return _map.data[p_index]; }\n    [[nodiscard]] const guint8& operator[](std::size_t p_index) const { return _map.data[p_index]; }\n\nprivate:\n    w_buffer_mapped_data() noexcept {}\n\n    /**\n     * @brief helper method to map raw buffer to a normal accessible data region.\n     * @param p_buffer raw gstreamer buffer.\n     * @param p_flags read/write flags. defaults to read-write.\n     */\n    [[nodiscard]] static auto make(internal::w_raw_tag,\n                                   GstBuffer* p_buffer,\n                                   w_buffer_map_flags p_flags = w_buffer_map_flags::ReadWrite)\n        -> boost::leaf::result<w_buffer_mapped_data>\n    {\n        auto ret = w_buffer_mapped_data();\n\n        auto flags_raw = static_cast<GstMapFlags>(p_flags);\n        if (!p_buffer || !gst_buffer_map(p_buffer, &ret._map, flags_raw)) {\n            return W_FAILURE(std::errc::operation_canceled, \"couldn't map the buffer data.\");\n        }\n\n        ret._buffer = p_buffer;\n\n        return ret;\n    }\n\n    GstBuffer* _buffer = nullptr;\n    GstMapInfo _map{};\n};\n\n/**\n * wrapper of GstBuffer.\n */\nclass w_buffer : public w_wrapper<w_buffer, GstBuffer, void, gst_buffer_unref>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    /**\n     * @brief make a buffer with given size.\n     * @return buffer on success.\n     */\n    [[nodiscard]] static auto make(std::size_t p_size) -> boost::leaf::result<w_buffer>;\n\n    /**\n     * @brief get timestamp in nanoseconds.\n     */\n    [[nodiscard]] auto get_timestamp() const noexcept\n    {\n        return GST_BUFFER_TIMESTAMP(raw());\n    }\n\n    /**\n     * @brief get duration of this buffer's playback in nanoseconds.\n     */\n    [[nodiscard]] auto get_duration() const noexcept\n    {\n        return raw()->duration;\n    }\n\n    /**\n     * @brief set timestamp in nanoseconds.\n     */\n    void set_timestamp(std::size_t p_nanoseconds) noexcept\n    {\n        GST_BUFFER_TIMESTAMP(raw()) = static_cast<GstClockTime>(p_nanoseconds);\n    }\n\n    /**\n     * @brief set duration of this buffer's playback in nanoseconds.\n     */\n    void set_duration(std::size_t p_nanoseconds) noexcept\n    {\n        raw()->duration = static_cast<GstClockTime>(p_nanoseconds);\n    }\n\n    /**\n     * @brief map to write-only data region.\n     */\n    [[nodiscard]] auto map_data_write()\n    {\n        return w_buffer_mapped_data::make(\n            internal::w_raw_tag{},\n            raw(),\n            w_buffer_map_flags::Write\n        );\n    }\n\n    /**\n     * @brief map to read-only data region.\n     */\n    [[nodiscard]] auto map_data_read() const\n    {\n        // NOTE unfortunately raw methods need pointer to non-const data, thus const_cast.\n        return w_buffer_mapped_data::make(\n            internal::w_raw_tag{},\n            const_cast<GstBuffer*>(raw()),\n            w_buffer_map_flags::Read\n        );\n    }\n\n    /**\n     * @brief map to readable-writable data region.\n     */\n    [[nodiscard]] auto map_data()\n    {\n        return w_buffer_mapped_data::make(internal::w_raw_tag{}, raw());\n    }\n\n    /**\n     * @brief map to readable data region.\n     */\n    [[nodiscard]] auto map_data() const\n    {\n        return map_data_read();\n    }\n\nprivate:\n    explicit w_buffer(internal::w_raw_tag, GstBuffer* p_buffer) noexcept\n        : w_wrapper(p_buffer)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_bus.cpp",
    "content": "#include \"media/gst/core/w_bus.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_bus.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_signal_handler.hpp\"\n#include \"media/gst/core/w_message.hpp\"\n#include \"media/gst/internal/w_wrapper.hpp\"\n\n#include <gst/gst.h>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrapper of GstBus. a bus to send messages to and notify listeners.\n */\nclass w_bus : public w_wrapper<w_bus, GstBus, void, gst_object_unref>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    w_bus() = delete;\n\n    w_bus(const w_bus&) = delete;\n    w_bus(w_bus&&) noexcept = default;\n\n    w_bus& operator=(const w_bus&) = delete;\n    w_bus& operator=(w_bus&&) noexcept = default;\n\n    ~w_bus() noexcept\n    {\n        for (auto i = 0u; i < _watch_count; ++i) {\n            gst_bus_remove_signal_watch(raw());\n        }\n    }\n\n    /**\n     * @brief hook a listener handler on message signal.\n     * @param p_handler message listener handler. it will be passed `w_nonowning<w_message>`.\n     */\n    template <typename F>\n    void hook_message(F&& p_handler)\n    {\n        ensure_watch();\n        constexpr auto invoker = +[](GstBus* /* p_self */, GstMessage* p_message, gpointer p_callee) {\n            auto& func = (*static_cast<decltype(_sighandlers.message)::handler_type*>(p_callee));\n            func(internal::w_raw_access::from_raw<w_nonowning<w_message>>(p_message));\n        };\n        _sighandlers.message.hook(\"message\", invoker, std::forward<F>(p_handler));\n    }\n\n    /**\n     * @brief unhook the message listener handler on message signal.\n     */\n    void unhook_message()\n    {\n        if (_sighandlers.message.unhook()) {\n            gst_bus_remove_signal_watch(raw());\n            --_watch_count;\n        }\n    }\n\nprivate:\n    explicit w_bus(internal::w_raw_tag, GstBus* p_bus_raw) noexcept\n        : w_wrapper(p_bus_raw)\n        , _sighandlers(G_OBJECT(p_bus_raw))\n    {}\n\n    /**\n     * @brief make sure there is at least one signal watch.\n     */\n    void ensure_watch() noexcept\n    {\n        if (_watch_count == 0) {\n            watch();\n        }\n    }\n\n    /**\n     * @brief add a signal watch so a listener can be added.\n     */\n    void watch() noexcept\n    {\n        gst_bus_add_signal_watch(raw());\n        ++_watch_count;\n    }\n\n    // signals\n    struct signal_handler_set {\n        w_signal_handler<w_nonowning<w_message>> message;\n\n        signal_handler_set(auto* p_rawptr) : message(p_rawptr) {}\n    } _sighandlers;\n\n    std::size_t _watch_count = 0;\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_caps.cpp",
    "content": "#include \"media/gst/core/w_caps.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_caps.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include \"media/gst/internal/w_common.hpp\"\n#include \"media/gst/internal/w_wrapper.hpp\"\n#include \"media/gst/core/w_structure.hpp\"\n\n#include <gst/gst.h>\n\n#include <string_view>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrapper of GstCaps, gstreamer capabilities concept.\n */\nclass w_caps : public w_wrapper<w_caps, GstCaps, void, gst_caps_unref>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    /**\n     * @brief make an empty caps.\n     * @return an instance of w_caps on success.\n     */\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_caps>\n    {\n        auto caps_raw = gst_caps_new_empty();\n        if (!caps_raw) {\n            return W_FAILURE(std::errc::operation_canceled,\n                             \"couldn't make caps.\");\n        }\n\n        return w_caps(internal::w_raw_tag{}, caps_raw);\n    }\n\n    /**\n     * @brief make a caps that acceps any kind of media.\n     * @return an instance of w_caps on success.\n     */\n    [[nodiscard]] static auto make_any() -> boost::leaf::result<w_caps>\n    {\n        auto caps_raw = gst_caps_new_any();\n        if (!caps_raw) {\n            return W_FAILURE(std::errc::operation_canceled,\n                             \"couldn't make caps as any.\");\n        }\n\n        return w_caps(internal::w_raw_tag{}, caps_raw);\n    }\n\n    /**\n     * @brief make an empty caps with media name.\n     * @return an instance of w_caps on success.\n     */\n    [[nodiscard]] static auto make_simple(const char* p_media_name)\n        -> boost::leaf::result<w_caps>\n    {\n        auto caps_raw = gst_caps_new_empty_simple(p_media_name);\n        if (!caps_raw) {\n            return W_FAILURE(\n                std::errc::operation_canceled,\n                \"couldn't make caps with given media name.\"\n            );\n        }\n\n        return w_caps(internal::w_raw_tag{}, caps_raw);\n    }\n\n    /**\n     * @brief add a capability structure.\n     * @param p_structure a capability structure.\n     */\n    void add(w_structure&& p_structure)\n    {\n        gst_caps_append_structure(raw(), internal::w_raw_access::disown_raw(p_structure));\n    }\n\nprivate:\n    w_caps(internal::w_raw_tag, GstCaps* p_caps_raw) noexcept\n        : w_wrapper(p_caps_raw)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_clock.cpp",
    "content": "#include \"media/gst/core/w_clock.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_clock.hpp",
    "content": "#pragma once\n\n#include \"media/gst/internal/w_wrapper.hpp\"\n\n#include <gst/gst.h>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrapper of GstClock.\n *\n * @note this class is not user constructible. it's nonowning by default.\n */\nclass w_clock : public w_wrapper<w_clock, GstClock, void, +[](GstClock*){ /* do nothing */ }>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    w_clock() = delete;\n\n    /**\n     * @brief get time in nanoseconds.\n     * @return time in nanoseconds.\n     */\n    std::size_t get_time() noexcept\n    {\n        return gst_clock_get_time(raw());\n    }\n\nprivate:\n    explicit w_clock(internal::w_raw_tag, GstClock* p_clock_raw) noexcept\n        : w_wrapper(p_clock_raw)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_element.cpp",
    "content": "#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\nauto w_element::make(const char *p_factory_name) -> boost::leaf::result<w_element>\n{\n    auto element_factory_raw = gst_element_factory_find(p_factory_name);\n    if (!element_factory_raw) {\n        auto err_msg = wolf::format(\"couldn't find factory name: {}\", p_factory_name);\n        return W_FAILURE(std::errc::operation_canceled, err_msg);\n    }\n\n    auto element_raw = gst_element_factory_create(element_factory_raw, nullptr);\n    if (!element_raw) {\n        auto err_msg = wolf::format(\n            \"couldn't create the element with given factory name: {}\",\n            p_factory_name\n        );\n        return W_FAILURE(std::errc::operation_canceled, err_msg);\n    }\n\n    if (G_IS_INITIALLY_UNOWNED(element_raw)) {\n        gst_object_ref_sink(element_raw);\n    }\n\n    return w_element(internal::w_raw_tag{}, element_raw);\n}\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_element.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include \"media/gst/internal/w_common.hpp\"\n#include \"media/gst/internal/w_wrapper.hpp\"\n#include \"media/gst/core/w_pad.hpp\"\n#include \"media/gst/core/w_clock.hpp\"\n\n#include <gst/gst.h>\n\n#include <stdexcept>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrapper of GstElement, gstreamer elements process stream data.\n *\n * elements combine to make dataflow pipeline graphs (DAG)\n * to process one or more media stream(s).\n */\nclass w_element : public w_wrapper<w_element, GstElement, void, gst_object_unref>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    /**\n     * @brief make an element by given factory name.\n     * @param p_factory_name element's factory name.\n     * @return an instance of element of given name on success.\n     */\n    [[nodiscard]] static auto make(const char* p_factory_name)\n        -> boost::leaf::result<w_element>;\n\n    w_element(const w_element&) = delete;\n    w_element(w_element&&) noexcept = default;\n\n    w_element& operator=(const w_element&) = delete;\n    w_element& operator=(w_element&&) noexcept = default;\n\n    virtual ~w_element() = default;\n\n    /**\n     * @brief get a request=pad with given name.\n     */\n    [[nodiscard]] auto request_pad(const char* p_pad_name)\n        -> boost::leaf::result<w_pad>\n    {\n        auto raw_pad = gst_element_request_pad_simple(raw(), p_pad_name);\n        if (!raw_pad) {\n            auto err_msg = wolf::format(\"request for pad `{}` failed.\", p_pad_name);\n            return W_FAILURE(std::errc::operation_canceled, err_msg);\n        }\n        return internal::w_raw_access::from_raw<w_pad>(raw_pad);\n    }\n\n    /**\n     * @brief get an always=pad with given name.\n     */\n    [[nodiscard]] auto always_pad(const char* p_pad_name)\n        -> boost::leaf::result<w_pad>\n    {\n        auto raw_pad = gst_element_get_static_pad(raw(), p_pad_name);\n        if (!raw_pad) {\n            auto err_msg = wolf::format(\"couldn't find always pad: `{}`\", p_pad_name);\n            return W_FAILURE(std::errc::operation_canceled, err_msg);\n        }\n        return internal::w_raw_access::from_raw<w_pad>(raw_pad);\n    }\n\n    /**\n     * @brief get element's clock.\n     */\n    w_nonowning<w_clock> clock() noexcept\n    {\n        return internal::w_raw_access::from_raw<w_nonowning<w_clock>>(raw()->clock);\n    }\n\nprivate:\n    explicit w_element(internal::w_raw_tag, GstElement* p_element) noexcept\n        : w_wrapper(p_element)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_element_factory.cpp",
    "content": "#include \"media/gst/core/w_element_factory.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_element_factory.hpp",
    "content": "#pragma once\n\n#include \"media/gst/internal/w_common.hpp\"\n#include \"media/gst/core/w_element.hpp\"\n\n#include <gst/gst.h>\n\n#include <optional>\n#include <utility>\n#include <stdexcept>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief gstreamer's element factory to create elements.\n */\nclass w_element_factory\n{\npublic:\n    w_element_factory() = delete;\n\n    /**\n     * @brief make an element from given gstreamer launch command.\n     * @param p_launch_str a gstreamer lauch command.\n     */\n    [[nodiscard]] static auto make_from_launch_str(const char* p_launch_str)\n        -> boost::leaf::result<w_element>\n    {\n        auto element_raw = gst_parse_launch(p_launch_str, nullptr);\n        if (!element_raw) {\n            return W_FAILURE(std::errc::operation_canceled,\n                             \"couldn't create element from launch string.\");\n        }\n\n        return internal::w_raw_access::from_raw<w_element>(element_raw);\n    }\n\n    /**\n     * @brief make a an element of given factory name, with given element name.\n     * @param p_factory_name name of element module.\n     * @param p_element_name custom name for element to reference later. (nullable)\n     * @return an element on success.\n     */\n    [[nodiscard]] static auto make_simple(const char* p_factory_name, const char* p_element_name)\n        -> boost::leaf::result<w_element>\n    {\n        auto element_raw = gst_element_factory_make(p_factory_name, p_element_name);\n        if (!element_raw) {\n            auto err_msg = wolf::format(\"couldn't create element with factory name: {}\", p_factory_name);\n            return W_FAILURE(std::errc::operation_canceled, err_msg);\n        }\n        return internal::w_raw_access::from_raw<w_element>(element_raw);\n    }\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_format.cpp",
    "content": "#include \"media/gst/core/w_format.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_format.hpp",
    "content": "#pragma once\n\n#include <gst/gst.h>\n\nnamespace wolf::media::gst {\n\n/** wrapper of GstFormat */\nenum class w_format\n{\n    Undefined = GST_FORMAT_UNDEFINED,\n    Default = GST_FORMAT_DEFAULT,\n    Bytes = GST_FORMAT_BYTES,\n    Time = GST_FORMAT_TIME,\n    Buffers = GST_FORMAT_BUFFERS,\n    Percent = GST_FORMAT_PERCENT\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_mainloop.cpp",
    "content": "#include \"media/gst/core/w_mainloop.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_mainloop.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include \"media/gst/internal/w_wrapper.hpp\"\n\n#include <gst/gst.h>\n\n#include <stdexcept>\n#include <functional>\n#include <utility>\n#include <vector>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrapper of GMainLoop, GLib's mainloop/eventloop facility.\n */\nclass w_mainloop : public w_wrapper<w_mainloop, GMainLoop, void, g_main_loop_unref>\n{\npublic:\n    /**\n     * @brief create a simple instance of mainloop.\n     * @return a w_mainloop instance on success.\n     */\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_mainloop>\n    {\n        auto main_loop_raw = g_main_loop_new(nullptr, false);\n        if (!main_loop_raw) {\n            return W_FAILURE(std::errc::operation_canceled,\n                             \"mainloop construction error.\");\n        }\n\n        return w_mainloop(internal::w_raw_tag{}, main_loop_raw);\n    }\n\n    /**\n     * @brief add a callable to be called on event loop idle times.\n     * @param p_func callable to be called on idle times.\n     * @return a sourceid to remove it later.\n     * @note `p_func` must have a consistent lifetime and address\n     *       until either being removed by `idle_remove` or the instance\n     *       of this class be destructed.\n     */\n    template <typename F>\n    std::size_t idle_add(F& p_func)\n    {\n        constexpr auto invoker = +[](F* p_funcptr) { (*p_funcptr)(); };\n        return g_idle_add(GSourceFunc(invoker), std::addressof(p_func));\n    }\n\n    bool idle_remove(std::size_t p_sourceid)\n    {\n        if (!p_sourceid) {\n            return false;\n        }\n\n        return g_source_remove(gsl::narrow_cast<int>(p_sourceid));\n    }\n\n    /**\n     * @brief run the main/event loop.\n     */\n    void run()\n    {\n        g_main_loop_run(raw());\n    }\n\n    /**\n     * @brief stop the main/event loop.\n     */\n    void stop()\n    {\n        g_main_loop_quit(raw());\n    }\n\nprivate:\n    w_mainloop(internal::w_raw_tag, GMainLoop* p_main_loop_raw) noexcept\n        : w_wrapper(p_main_loop_raw)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_message.cpp",
    "content": "#include \"media/gst/core/w_message.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_message.hpp",
    "content": "#pragma once\n\n#include \"media/gst/internal/w_common.hpp\"\n#include \"media/gst/internal/w_wrapper.hpp\"\n\n#include <gst/gst.h>\n\n#include <utility>\n\nnamespace wolf::media::gst {\n\nclass w_message;\n\n/** type of GstMessage */\nenum class w_message_type : std::size_t\n{\n    Unknown = 0,\n    EOS,\n    Error,\n    Warning,\n    Info\n};\n\n//- message structs\n\n/** the unknown variant of GstMessage */\nstruct w_message_unknown {};\n\n/** the end-of-stream variant of GstMessage */\nstruct w_message_eos {};\n\n/** the error message variant of GstMessage */\nstruct w_message_error\n{\n    friend class w_message;\n\npublic:\n    w_message_error() = delete;\n\n    w_message_error(const w_message_error&) = delete;\n\n    ~w_message_error() noexcept\n    {\n        if (_error) {\n            g_clear_error(&_error);\n        }\n\n        if (_debug_info) {\n            g_free(_debug_info);\n        }\n    }\n\n    /**\n     * @brief print the error message to standard output.\n     */\n    void print() const\n    {\n        g_printerr(\n            \"Error received from element %s: %s\\n\",\n            GST_OBJECT_NAME(_msg->src),\n            _error->message\n        );\n        g_printerr(\n            \"Debugging information: %s\\n\",\n            _debug_info ? _debug_info : \"none\"\n        );\n    }\n\nprivate:\n    /**\n     * @brief parse the message to extract error info.\n     */\n    explicit w_message_error(internal::w_raw_tag, GstMessage* p_msg_raw)\n        : _msg(p_msg_raw)\n    {\n        gst_message_parse_error(p_msg_raw, &_error, &_debug_info);\n    }\n\n    GstMessage* _msg = nullptr;  //< non-owning.\n    GError* _error = nullptr;\n    gchar* _debug_info = nullptr;\n};\n\n/**\n * @brief wrapper of GstMessage. gstreamer's ultimate message struct.\n *\n * there are so many different kinds and variants of message,\n * and all are represented by w_message.\n *\n * for ease of use, there are helper message representative classes,\n * which on visit the appropriate one will be created and passed to\n * given visitor.\n */\nclass w_message : public w_wrapper<w_message, GstMessage, void, gst_message_unref>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    // not supported yet.\n    w_message() = delete;\n\n//    w_message_type type() const noexcept\n//    {\n//        return convert_message_type(GST_MESSAGE_TYPE(msg_));\n//    }\n\n    /**\n     * @brief visit the message based on its type as the helper representative type.\n     * @param p_visitor visitor to visit message variant.\n     */\n    template <typename VisitorF>\n    auto visit(VisitorF&& p_visitor)\n    {\n        return raw_visit(std::forward<VisitorF>(p_visitor), raw());\n    }\n\nprivate:\n    explicit w_message(internal::w_raw_tag, GstMessage* p_msg_raw)\n        : w_wrapper(p_msg_raw)\n    {}\n\n    /**\n     * @brief create and visit appropriate repr variant by given raw message and visitor.\n     * @param p_visitor visitor to visit message variant.\n     * @param p_msg_raw raw message pointer.\n     */\n    template <typename VisitorF>\n    static auto raw_visit(VisitorF&& p_visitor, GstMessage* p_msg_raw)\n    {\n        switch (GST_MESSAGE_TYPE(p_msg_raw)) {\n            case GST_MESSAGE_EOS:\n                return std::forward<VisitorF>(w_message_eos{});\n            case GST_MESSAGE_ERROR:\n                return std::forward<VisitorF>(p_visitor)(\n                    w_message_error(internal::w_raw_tag{}, p_msg_raw)\n                );\n            default: // GST_MESSAGE_UNKNOWN\n                return std::forward<VisitorF>(p_visitor)(w_message_unknown{});\n        }\n    }\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_nonowning.cpp",
    "content": "#include \"media/gst/core/w_nonowning.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_nonowning.hpp",
    "content": "#pragma once\n\n#include \"media/gst/internal/w_common.hpp\"\n\n#include <utility>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief nonowning view of `T` pointing to same resource\n *        given to make nonowning view of. similar to std::string_view/std::span.\n *\n * it's for sharing things like element.clock() returning Clock instance,\n * which the instance does not own the clock's lifetime, but\n * points to same resource to keep track of.\n *\n * this class is wrapper acting as a pointer to an instance of `T`\n * with shared resource beneath.\n *\n * @tparam T underlying type of nonowning view.\n *\n * @note make sure the given object lives longer than this nonowning view of it,\n *       or any access will be undefined behavior.\n *       similar to std::string_view or std::span.\n */\ntemplate <typename T>\nclass w_nonowning\n{\n    friend class internal::w_raw_access;\n\n    using value_type = std::remove_cvref_t<T>;\n\npublic:\n    /**\n     * @brief implicit constructor from a value of wrapping type.\n     * @param p_value value to make nonowing view of.\n     */\n    w_nonowning(value_type& p_value)\n        : w_nonowning(internal::w_raw_access::raw(p_value))\n    {}\n\n    w_nonowning(const w_nonowning&) = default;\n    w_nonowning(w_nonowning&&) noexcept = default;\n\n    w_nonowning& operator=(const w_nonowning&) = default;\n    w_nonowning& operator=(w_nonowning&&) noexcept = default;\n\n    ~w_nonowning() noexcept\n    {\n        // disown raw resource before resource\n        // be released/free'ed by T's destructor.\n        internal::w_raw_access::disown_raw(_value);\n    }\n\n    value_type* operator->() noexcept { return std::addressof(_value); }\n    const value_type* operator->() const noexcept { return std::addressof(_value); }\n\n    value_type& operator*() noexcept { return _value; }\n    const value_type& operator*() const noexcept { return _value; }\n\nprivate:\n    template <typename RawT>\n    w_nonowning(internal::w_raw_tag, RawT* p_rawptr) noexcept\n        : _value(internal::w_raw_access::from_raw<value_type>(p_rawptr))\n    {}\n\n    value_type _value;\n};\n\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_pad.cpp",
    "content": "#include \"media/gst/core/w_pad.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_pad.hpp",
    "content": "#pragma once\n\n#include \"media/gst/internal/w_common.hpp\"\n#include \"media/gst/internal/w_wrapper.hpp\"\n\n#include <gst/gst.h>\n\n#include <utility>\n\nnamespace wolf::media::gst {\n\n/** gstreamer pad availablity */\nenum class w_availability\n{\n    Always,\n    Request,\n    Sometimes\n};\n\n/**\n * @brief wrapper of GstPad.\n *\n * each gstreamer element has source and/or sink pads,\n * which they connect by to each other with.\n */\nclass w_pad : public w_wrapper<w_pad, GstPad, void, gst_object_unref>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    // so far nothing...\n\nprivate:\n    explicit w_pad(internal::w_raw_tag, GstPad* p_pad) noexcept\n        : w_wrapper(p_pad)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_pipeline.cpp",
    "content": "#include \"media/gst/core/w_pipeline.hpp\"\n\nnamespace wolf::media::gst {\n\nauto w_pipeline::make(const char *p_name)\n    -> boost::leaf::result<w_pipeline>\n{\n    auto pipeline_raw = gst_pipeline_new(p_name);\n    if (!pipeline_raw) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         wolf::format(\"couldn't create pipeline: {}\", p_name));\n    }\n    return w_pipeline(internal::w_raw_tag{}, pipeline_raw);\n}\n\nauto w_pipeline::get_bus() -> boost::leaf::result<w_bus>\n{\n    auto bus_raw = gst_element_get_bus(raw());\n    if (!bus_raw) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"couldn't get pipeline's bus.\");\n    }\n    return internal::w_raw_access::from_raw<w_bus>(bus_raw);\n}\n\nbool w_pipeline::bin(w_flow_path &p_flow)\n{\n    for (auto& element : p_flow) {\n        if (!bin(*element)) {\n            return false;\n        }\n    }\n\n    return true;\n}\n\nbool w_pipeline::link(w_flow_path &p_flow)\n{\n    auto* last = p_flow.first().get();\n    for (int i = 1; i < p_flow.size(); ++i) {\n        if (!link(*last, *p_flow[i])) {\n            return false;\n        }\n\n        last = p_flow[i].get();\n    }\n\n    return true;\n}\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_pipeline.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include \"media/gst/w_flow.hpp\"\n#include \"media/gst/core/w_element.hpp\"\n#include \"media/gst/core/w_bus.hpp\"\n#include \"media/gst/internal/w_wrapper.hpp\"\n\n#include <gst/gst.h>\n\n#include <string_view>\n#include <stdexcept>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrapper of GstElement, providing gstreamer pipeline concept.\n */\nclass w_pipeline : public w_wrapper<w_pipeline, GstElement, void, gst_object_unref>\n{\npublic:\n    /**\n     * @brief make an instance of pipeline with given name.\n     * @param p_name pipeline's name.\n     * @return an instance of pipeline on success.\n     */\n    [[nodiscard]] static auto make(const char* p_name)\n        -> boost::leaf::result<w_pipeline>;\n\n    /**\n     * @brief get pipeline's bus.\n     */\n    [[nodiscard]] auto get_bus() -> boost::leaf::result<w_bus>;\n\n    /**\n     * @brief add given elements to pipeline's bin.\n     * @param p_args pack of elements.\n     * @return boolean indicating success or failure.\n     */\n    template <typename ...Args>\n        requires (sizeof...(Args) > 1)\n    bool bin(Args&& ...p_args)\n    {\n        return (true && ... && bin(std::forward<Args>(p_args)));\n    }\n\n    /**\n     * @brief add elements from given flow path to pipeline's bin.\n     * @param p_flow elements flow path.\n     * @return boolean indicating success or failure.\n     */\n    bool bin(w_flow_path& p_flow);\n\n    /**\n     * @brief add given single element to pipeline's bin.\n     * @param p_element single element.\n     * @return boolean indicating success or failure.\n     */\n    bool bin(w_element& p_element)\n    {\n        auto element_raw = internal::w_raw_access::raw(p_element);\n        p_element.parented();\n        return gst_bin_add(GST_BIN(raw()), element_raw);\n    }\n\n    /**\n     * @brief link a pack of given linkables (element or pad) together after each other.\n     * @param p_a source linkable to link with `p_b`.\n     * @param p_b sink linkable to link with `p_a`.\n     * @param p_rest pack of rest of linkables to be linked after `p_b` as source.\n     * @return boolean indicating success or failure.\n     */\n    template <typename T, typename U, typename ...Rest>\n    bool link(T&& p_a, U&& p_b, Rest&& ...p_rest)\n    {\n        auto raw_a = internal::w_raw_access::raw(p_a);\n        auto raw_b = internal::w_raw_access::raw(p_b);\n\n        if (!gst_element_link(raw_a, raw_b)) {\n            return false;\n        }\n\n        if constexpr (sizeof...(Rest) > 0) {\n            return link(std::forward<U>(p_b), std::forward<Rest>(p_rest)...);\n        }\n\n        return true;\n    }\n\n    /**\n     * @brief link two elements.\n     * @param p_src source element.\n     * @param p_sink sink element.\n     * @return boolean indicating success or failure.\n     */\n    bool link(w_element& p_src, w_element& p_sink)\n    {\n        return gst_element_link(\n            internal::w_raw_access::raw(p_src),\n            internal::w_raw_access::raw(p_sink)\n        );\n    }\n\n    /**\n     * @brief link a flow path's elements after each other.\n     * @param p_flow flow path set of elements.\n     * @return boolean indicating success or failure.\n     */\n    bool link(w_flow_path& p_flow);\n\n    /**\n     * @brief set the pipeline to play state.\n     * @return boolean indicating success or failure.\n     */\n    bool play()\n    {\n        return static_cast<bool>(gst_element_set_state(raw(), GST_STATE_PLAYING));\n    }\n\n    /**\n     * @brief set the pipeline to pause state.\n     * @return boolean indicating success or failure.\n     */\n    bool pause()\n    {\n        return static_cast<bool>(gst_element_set_state(raw(), GST_STATE_PAUSED));\n    }\n\n    /**\n     * @brief set the pipeline to stop state.\n     * @return boolean indicating success or failure.\n     */\n    bool stop() {\n        return static_cast<bool>(gst_element_set_state(raw(), GST_STATE_NULL));\n    }\n\nprivate:\n    w_pipeline(internal::w_raw_tag, GstElement* pipeline_raw) noexcept\n        : w_wrapper(pipeline_raw)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_refptr.cpp",
    "content": "#include \"media/gst/core/w_refptr.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_refptr.hpp",
    "content": "#pragma once\n\n#include <boost/leaf.hpp>\n\n#include <type_traits>\n#include <memory>\n\nnamespace wolf::media::gst {\n\n/**\n * shared ref-counting smart pointer of given `T`.\n *\n * @tparam T type to wrap shared reference to.\n */\ntemplate <typename T>\nusing w_refptr = std::shared_ptr<T>;\n\n/**\n * @brief convert given value to a ref-counting smart pointer.\n * @param p_value value to make shared.\n * @return sharable ref-counting refptr.\n */\ntemplate <typename T>\ninline w_refptr<T> to_refptr(T&& p_value)\n{\n    using type = std::remove_cvref_t<T>;\n    return std::make_shared<type>(std::forward<T>(p_value));\n}\n\n/**\n * @brief convert given value to a ref-counting smart pointer.\n * @param p_value a refptr to increase its ref-count.\n * @return another copy of given refptr pointing to same value.\n */\ntemplate <typename T>\ninline w_refptr<T> to_refptr(w_refptr<T> p_value)\n{\n    return p_value;\n}\n\n//template <typename T>\n//inline w_refptr<T> to_refptr(boost::leaf::result<T> p_value)\n//{\n//    if (!p_value) {\n//        return w_refptr<T>(nullptr);\n//    }\n//    return to_refptr<T>(std::move(*p_value));\n//}\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_signal_handler.cpp",
    "content": "#include \"media/gst/core/w_signal_handler.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/core/w_signal_handler.hpp",
    "content": "#pragma once\n\n#include \"media/gst/internal/w_common.hpp\"\n\n#include <gst/gst.h>\n\n#include <functional>\n#include <utility>\n#include <stdexcept>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief internal signal handler to use in signallable wrappers.\n *\n * it holds the handler and takes ownership of its lifetime,\n * and unhook at destruction.\n *\n * @tparam Args pack of args that will be passed to hooked signal handler.\n */\ntemplate <typename ...Args>\nclass w_signal_handler\n{\npublic:\n    using rawptr_type = GObject*;\n    using handler_type = std::function<void(Args...)>;\n    using handlerid_type = gulong;\n\n    constexpr static auto simple_invoker =\n        +[](GObject* /* p_instance */, Args ...p_args, void* p_callee) {\n            (*static_cast<handler_type*>(p_callee))(std::move(p_args)...);\n        };\n\n    /**\n     * @brief make signal handler of given gobject instance.\n     * @param p_rawptr gobject instance to hook/unhook signal on.\n     */\n    explicit w_signal_handler(rawptr_type p_rawptr)\n        : _rawptr(p_rawptr)\n    {\n        // fatal error, this shouldn't be caught but to terminate.\n        if (!p_rawptr) {\n            throw std::invalid_argument(\"given raw pointer to handle signals is null.\");\n        }\n    }\n\n    w_signal_handler(const w_signal_handler&) = delete;\n    w_signal_handler(w_signal_handler&&) noexcept = default;\n\n    w_signal_handler& operator=(const w_signal_handler&) = delete;\n    w_signal_handler& operator=(w_signal_handler&&) noexcept = default;\n\n    ~w_signal_handler() noexcept { unhook(); }\n\n    /**\n     * @brief hook given handler on given signal name with given invoker.\n     * @param p_name    name of signal to hook.\n     * @param p_invoker invoker is raw signal handler\n     *                  which will invoke given handler by converted args.\n     * @param p_handler user handler to handle named signal.\n     * @return boolean indicating successful hook or not.\n     * @note invoker does raw convertions too.\n     */\n    template <std::invocable<Args...> F>\n    bool hook(const char* p_name, auto* p_invoker, F&& p_handler)\n    {\n        unhook();\n\n        auto handlerid = g_signal_connect(\n            _rawptr,\n            p_name,\n            (GCallback)p_invoker,\n            (void*)std::addressof(_handler)\n        );\n        if (!handlerid) {\n            return false;\n        }\n\n        _handler = std::forward<F>(p_handler);\n        _handlerid = handlerid;\n\n        return true;\n    }\n\n    /**\n     * @brief hook given handler on given signal name with given invoker.\n     * @param p_name    name of signal to hook.\n     * @param p_handler user handler to handle named signal.\n     * @return boolean indicating successful hook or not.\n     */\n    template <std::invocable<Args...> F>\n    bool hook(const char* p_name, F&& p_handler)\n    {\n        // simple invoker without type conversion.\n        return hook(p_name, simple_invoker, std::forward<F>(p_handler));\n    }\n\n    /**\n     * @brief unhook and release the previously hooked handler.\n     * @return boolean indicating success or failure.\n     *         returns false if nothing was hooked already.\n     */\n    bool unhook() noexcept\n    {\n        if (!_handlerid) {\n            return false;\n        }\n\n        g_signal_handler_disconnect(_rawptr, _handlerid);\n        _handlerid = 0;\n\n        _handler = {};\n\n        return true;\n    }\n\nprivate:\n    rawptr_type _rawptr = nullptr;  //< non-onwing.\n    handler_type _handler{};\n    handlerid_type _handlerid{};\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_structure.cpp",
    "content": "#include \"media/gst/core/w_structure.hpp\"\n\nnamespace wolf::media::gst {\n\nauto w_structure::make(const char *p_name)\n    -> boost::leaf::result<w_structure>\n{\n    auto structure_raw = gst_structure_new_empty(p_name);\n    if (!structure_raw) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"couldn't create structure.\");\n    }\n\n    return w_structure(internal::w_raw_tag{}, structure_raw);\n}\n\nauto w_structure::make_from_str(const char *p_str) -> boost::leaf::result<w_structure>\n{\n    auto structure_raw = gst_structure_from_string(p_str, nullptr);\n    if (!structure_raw) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"couldn't create structure from given string repr.\");\n    }\n\n    return w_structure(internal::w_raw_tag{}, structure_raw);\n}\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/core/w_structure.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include \"media/gst/internal/w_wrapper.hpp\"\n\n#include <gst/gst.h> // use specific headers or forward-declare\n\n#include <string_view>\n#include <concepts>\n\nnamespace wolf::media::gst {\n\nstruct w_fraction\n{\n    std::size_t numerator;\n    std::size_t denomerator = 1;\n};\n\n/**\n * @brief wrapper of GstStructure, commonly used to represent a single gstreamer caps.\n */\nclass w_structure : public w_wrapper<w_structure, GstStructure, void, gst_structure_free>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    /**\n     * @brief make an instance of structure with given name.\n     * @param p_name name of cap strucutre.\n     * @return instance of structure on success.\n     */\n    [[nodiscard]] static auto make(const char* p_name)\n        -> boost::leaf::result<w_structure>;\n\n    /**\n     * @brief make structure cap from given string representation.\n     * @param p_str gstreamer string repr of a structure.\n     * @return instance of structure on success.\n     */\n    [[nodiscard]] static auto make_from_str(const char* p_str)\n        -> boost::leaf::result<w_structure>;\n\n    /**\n     * @brief set name/value pairs of feilds.\n     */\n    template <typename T, typename ...Rest>\n    void set_field_pairs(const char* p_fieldname, T&& p_fieldvalue, Rest&& ...p_rest)\n    {\n        set_field(p_fieldname, std::forward<T>(p_fieldvalue));\n\n        if constexpr (sizeof...(Rest) > 0) {\n            set_field_pairs(std::forward<Rest>(p_rest)...);\n        }\n    }\n\n    /**\n     * @brief set a fraction field.\n     */\n    void set_field(const char* p_fieldname, w_fraction p_fraction)\n    {\n        gst_structure_set(\n            raw(),\n            p_fieldname,\n            GST_TYPE_FRACTION,\n            p_fraction.numerator,\n            p_fraction.denomerator,\n            nullptr\n        );\n    }\n\n    /**\n     * @brief set uint64 field.\n     */\n    void set_field(const char* p_fieldname, std::size_t p_value)\n    {\n        gst_structure_set(raw(), p_fieldname, G_TYPE_UINT64, p_value, nullptr);\n    }\n\nprivate:\n    w_structure(internal::w_raw_tag, GstStructure* p_structure_raw)\n        : w_wrapper(p_structure_raw)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_aacparse.cpp",
    "content": "#include \"media/gst/elements/w_element_aacparse.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_aacparse.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of aacparse gstreamer element.\n */\nclass w_element_aacparse : public w_element\n{\n    constexpr static const char* factory_name = \"aacparse\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_aacparse>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_aacparse(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_aacparse(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_appsrc.cpp",
    "content": "#include \"media/gst/elements/w_element_appsrc.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_appsrc.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n#include \"media/gst/core/w_signal_handler.hpp\"\n#include \"media/gst/core/w_caps.hpp\"\n#include \"media/gst/core/w_format.hpp\"\n\n#include <gst/gst.h>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of appsrc gstreamer element.\n */\nclass w_element_appsrc : public w_element\n{\n    constexpr static const char* factory_name = \"appsrc\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_appsrc>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_appsrc(std::move(base_element));\n    }\n\n    //- properties\n\n    void set_block(bool p_block) {\n        g_object_set(raw(), \"block\", p_block, nullptr);\n    }\n\n    void set_caps(w_caps& p_caps)\n    {\n        g_object_set(raw(), \"caps\", internal::w_raw_access::raw(p_caps), nullptr);\n    }\n\n    void set_format(w_format p_format)\n    {\n        g_object_set(raw(), \"format\", static_cast<GstFormat>(p_format), nullptr);\n    }\n\n    void set_live(bool p_is_live)\n    {\n        g_object_set(raw(), \"is-live\", p_is_live, nullptr);\n    }\n\n    void set_max_buffer(std::size_t p_count)\n    {\n        g_object_set(raw(), \"max-buffers\", p_count, nullptr);\n    }\n\n    void set_max_latency(std::size_t p_nanoseconds)\n    {\n        g_object_set(raw(), \"max-latency\", p_nanoseconds, nullptr);\n    }\n\n    void set_max_time(std::size_t p_nanoseconds)\n    {\n        g_object_set(raw(), \"max-time\", p_nanoseconds, nullptr);\n    }\n\n    //- signals\n\n    template <typename F>\n    void hook_enough_data(F&& p_callback)\n    {\n        _sighandlers.enough_data.hook(\"enough-data\", std::forward<F>(p_callback));\n    }\n\n    void unhook_enough_data()\n    {\n        _sighandlers.seek_data.unhook();\n    }\n\n    template <typename F>\n    void hook_need_data(F&& p_callback)\n    {\n        _sighandlers.need_data.hook(\"need-data\", std::forward<F>(p_callback));\n    }\n\n    void unhook_need_data()\n    {\n        _sighandlers.seek_data.unhook();\n    }\n\n    template <typename F>\n    void hook_seek_data(F&& p_callback)\n    {\n        _sighandlers.seek_data.hook(\"seek-data\", std::forward<F>(p_callback));\n    }\n\n    void unhook_seek_data()\n    {\n        _sighandlers.seek_data.unhook();\n    }\n\n    //- action signals\n\n    bool emit_eos()\n    {\n        GstFlowReturn ret;\n        g_signal_emit_by_name(raw(), \"end-of-stream\", &ret);\n        return static_cast<bool>(ret);\n    }\n\n    template <typename BufferT>\n    bool emit_push_buffer(BufferT&& p_buffer)\n    {\n        GstFlowReturn ret;\n        g_signal_emit_by_name(raw(), \"push-buffer\", internal::w_raw_access::raw(p_buffer), &ret);\n        return static_cast<bool>(ret);\n    }\n\nprivate:\n    explicit w_element_appsrc(w_element&& p_base)\n        : w_element(std::move(p_base))\n        , _sighandlers(G_OBJECT(raw()))\n    {}\n\n    // signals\n    struct signal_handler_set {\n        w_signal_handler<> enough_data;\n        w_signal_handler<std::size_t> need_data; /// params: length\n        w_signal_handler<std::size_t> seek_data; /// params: offset\n\n        signal_handler_set(auto* p_rawptr)\n            : enough_data(p_rawptr)\n            , need_data(p_rawptr)\n            , seek_data(p_rawptr)\n        {}\n    } _sighandlers;\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_audioconvert.cpp",
    "content": "#include \"media/gst/elements/w_element_audioconvert.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_audioconvert.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of audioconvert gstreamer element.\n */\nclass w_element_audioconvert : public w_element\n{\n    constexpr static const char* factory_name = \"audioconvert\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_audioconvert>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_audioconvert(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_audioconvert(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_audioresample.cpp",
    "content": "#include \"media/gst/elements/w_element_audioresample.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_audioresample.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of audioresample gstreamer element.\n */\nclass w_element_audioresample : public w_element\n{\n    constexpr static const char* factory_name = \"audioresample\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_audioresample>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_audioresample(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_audioresample(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_autovideosink.cpp",
    "content": "#include \"media/gst/elements/w_element_autovideosink.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_autovideosink.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\n#include <gst/gst.h>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of audiovideosink gstreamer element.\n */\nclass w_element_autovideosink : public w_element\n{\n    constexpr static const char* factory_name = \"autovideosink\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_autovideosink>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_autovideosink(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_autovideosink(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_avencflv.cpp",
    "content": "#include \"media/gst/elements/w_element_avencflv.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_avencflv.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of avencflv gstreamer element.\n */\nclass w_element_avencflv : public w_element\n{\n    constexpr static const char* factory_name = \"avenc_flv\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_avencflv>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_avencflv(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_avencflv(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_capsfilter.cpp",
    "content": "#include \"media/gst/elements/w_element_capsfilter.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_capsfilter.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n#include \"media/gst/core/w_caps.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of capsfilter gstreamer element.\n */\nclass w_element_capsfilter : public w_element\n{\n    constexpr static const char* factory_name = \"capsfilter\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_capsfilter>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_capsfilter(std::move(base_element));\n    }\n\n    void set_caps(w_caps& p_caps)\n    {\n        g_object_set(raw(), \"caps\", internal::w_raw_access::raw(p_caps), nullptr);\n    }\n\nprivate:\n    explicit w_element_capsfilter(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_filesink.cpp",
    "content": "#include \"media/gst/elements/w_element_filesink.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_filesink.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of filesink gstreamer element.\n */\nclass w_element_filesink : public w_element\n{\n    constexpr static const char* factory_name = \"filesink\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_filesink>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_filesink(std::move(base_element));\n    }\n\n    void set_location(const char* p_location)\n    {\n        g_object_set(raw(), \"location\", p_location, nullptr);\n    }\n\nprivate:\n    explicit w_element_filesink(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_flvmux.cpp",
    "content": "#include \"media/gst/elements/w_element_flvmux.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_flvmux.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of flvmux gstreamer element.\n */\nclass w_element_flvmux : public w_element\n{\n    constexpr static const char* factory_name = \"flvmux\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_flvmux>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_flvmux(std::move(base_element));\n    }\n\n    void set_streamable(bool p_streamable)\n    {\n        g_object_set(raw(), \"streamable\", p_streamable, nullptr);\n    }\n\nprivate:\n    explicit w_element_flvmux(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_h264parse.cpp",
    "content": "#include \"media/gst/elements/w_element_h264parse.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_h264parse.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of h264parse gstreamer element.\n */\nclass w_element_h264parse : public w_element\n{\n    constexpr static const char* factory_name = \"h264parse\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_h264parse>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_h264parse(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_h264parse(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_mp4mux.cpp",
    "content": "#include \"media/gst/elements/w_element_mp4mux.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_mp4mux.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of mp4mux gstreamer element.\n */\nclass w_element_mp4mux : public w_element\n{\n    constexpr static const char* factory_name = \"mp4mux\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_mp4mux>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_mp4mux(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_mp4mux(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_openh264enc.cpp",
    "content": "#include \"media/gst/elements/w_element_openh264enc.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_openh264enc.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of openh264enc gstreamer element.\n */\nclass w_element_openh264enc : public w_element\n{\n    constexpr static const char* factory_name = \"openh264enc\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_openh264enc>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_openh264enc(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_openh264enc(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_queue.cpp",
    "content": "#include \"media/gst/elements/w_element_queue.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_queue.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of queue gstreamer element.\n */\nclass w_element_queue : public w_element\n{\n    constexpr static const char* factory_name = \"queue\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_queue>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_queue(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_queue(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_rtmpsink.cpp",
    "content": "#include \"media/gst/elements/w_element_rtmpsink.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_rtmpsink.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of rtmpsink gstreamer element.\n */\nclass w_element_rtmpsink : public w_element\n{\n    constexpr static const char* factory_name = \"rtmpsink\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_rtmpsink>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_rtmpsink(std::move(base_element));\n    }\n\n    void set_location(const char* p_location)\n    {\n        g_object_set(raw(), \"location\", p_location, nullptr);\n    }\n\nprivate:\n    explicit w_element_rtmpsink(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_rtph264pay.cpp",
    "content": "#include \"media/gst/elements/w_element_rtph264pay.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_rtph264pay.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of rtph264pay gstreamer element.\n */\nclass w_element_rtph264pay : public w_element\n{\n    constexpr static const char* factory_name = \"rtph264pay\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_rtph264pay>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_rtph264pay(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_rtph264pay(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_udpsink.cpp",
    "content": "#include \"media/gst/elements/w_element_udpsink.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_udpsink.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of udpsink gstreamer element.\n */\nclass w_element_udpsink : public w_element\n{\n    constexpr static const char* factory_name = \"udpsink\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_udpsink>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_udpsink(std::move(base_element));\n    }\n\n    void set_host(const char* p_host)\n    {\n        g_object_set(raw(), \"host\", p_host, nullptr);\n    }\n\n    void set_port(unsigned short p_port)\n    {\n        g_object_set(raw(), \"port\", static_cast<gint>(p_port), nullptr);\n    }\n\nprivate:\n    explicit w_element_udpsink(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_videoconvert.cpp",
    "content": "#include \"media/gst/elements/w_element_videoconvert.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_videoconvert.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of videoconvert gstreamer element.\n */\nclass w_element_videoconvert : public w_element\n{\n    constexpr static const char* factory_name = \"videoconvert\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_videoconvert>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_videoconvert(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_videoconvert(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_videoscale.cpp",
    "content": "#include \"media/gst/elements/w_element_videoscale.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_videoscale.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of videoscale gstreamer element.\n */\nclass w_element_videoscale : public w_element\n{\n    constexpr static const char* factory_name = \"videoscale\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_videoscale>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_videoscale(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_videoscale(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_videotestsrc.cpp",
    "content": "#include \"media/gst/elements/w_element_videotestsrc.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_videotestsrc.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of videotestsrc gstreamer element.\n */\nclass w_element_videotestsrc : public w_element\n{\n    constexpr static const char* factory_name = \"videotestsrc\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_videotestsrc>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_videotestsrc(std::move(base_element));\n    }\n\nprivate:\n    explicit w_element_videotestsrc(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_voaacenc.cpp",
    "content": "#include \"media/gst/elements/w_element_voaacenc.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_voaacenc.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of voaacenc gstreamer element.\n */\nclass w_element_voaacenc : public w_element\n{\n    constexpr static const char* factory_name = \"voaacenc\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_voaacenc>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_voaacenc(std::move(base_element));\n    }\n\n    void set_bitrate(std::size_t p_bitrate)\n    {\n        g_object_set(raw(), \"bitrate\", p_bitrate, nullptr);\n    }\n\nprivate:\n    explicit w_element_voaacenc(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_wasapisrc.cpp",
    "content": "#include \"media/gst/elements/w_element_wasapisrc.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_wasapisrc.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of wasapisrc gstreamer element.\n */\nclass w_element_wasapisrc : public w_element\n{\n    constexpr static const char* factory_name = \"wasapisrc\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_wasapisrc>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_wasapisrc(std::move(base_element));\n    }\n\n    void set_device(const char* p_device)\n    {\n        g_object_set(raw(), \"device\", p_device, nullptr);\n    }\n\n    void set_low_latency(bool p_enable)\n    {\n        g_object_set(raw(), \"low-latency\", p_enable, nullptr);\n    }\n\nprivate:\n    explicit w_element_wasapisrc(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_x264enc.cpp",
    "content": "#include \"media/gst/elements/w_element_x264enc.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/elements/w_element_x264enc.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_element.hpp\"\n\nnamespace wolf::media::gst {\n\n/**\n * @brief wrappper of x264enc gstreamer element.\n */\nclass w_element_x264enc : public w_element\n{\n    constexpr static const char* factory_name = \"x264enc\";\n\npublic:\n    [[nodiscard]] static auto make() -> boost::leaf::result<w_element_x264enc>\n    {\n        BOOST_LEAF_AUTO(base_element, w_element::make(factory_name));\n        return w_element_x264enc(std::move(base_element));\n    }\n\n    void set_bitrate(std::size_t p_bitrate)\n    {\n        g_object_set(raw(), \"bitrate\", p_bitrate, nullptr);\n    }\n\n    void set_pass(std::size_t p_pass)\n    {\n        g_object_set(raw(), \"pass\", p_pass, nullptr);\n    }\n\n    void set_quantizer(std::size_t p_quantizer)\n    {\n        g_object_set(raw(), \"quantizer\", p_quantizer, nullptr);\n    }\n\n    void set_qp_min(std::size_t p_qp_min)\n    {\n        g_object_set(raw(), \"qp-min\", p_qp_min, nullptr);\n    }\n\n    void set_qp_max(std::size_t p_qp_max)\n    {\n        g_object_set(raw(), \"qp-max\", p_qp_max, nullptr);\n    }\n\n    void set_speed_preset(std::size_t p_speed_preset)\n    {\n        g_object_set(raw(), \"speed-preset\", p_speed_preset, nullptr);\n    }\n\n    void set_key_int_max(std::size_t p_key_int_max)\n    {\n        g_object_set(raw(), \"key-int-max\", p_key_int_max, nullptr);\n    }\n\n    void set_b_adapt(bool p_b_adapt)\n    {\n        g_object_set(raw(), \"b-adapt\", p_b_adapt, nullptr);\n    }\n\n    void set_bframes(std::size_t p_bframes)\n    {\n        g_object_set(raw(), \"bframes\", p_bframes, nullptr);\n    }\n\nprivate:\n    explicit w_element_x264enc(w_element&& p_base) noexcept\n        : w_element(std::move(p_base))\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/internal/w_common.cpp",
    "content": "#include \"media/gst/internal/w_common.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/internal/w_common.hpp",
    "content": "#pragma once\n\n#include <utility>\n\nnamespace wolf::media::gst::internal {\n\n/** tag to indicate having a raw pointer in the context. */\nstruct w_raw_tag {};\n\n/**\n * @brief helper utility to be common friend of wrappers,\n *        poviding access to certain api for any wrapper to another.\n *\n * this comes handy when w_audio_info wants to create a w_caps,\n * or w_pipeline wants to add w_element to its bin.\n *\n * instead of having the aformentioned types know/befriend each other,\n * they'll be friend to this class and provide private access to this,\n * so any of them can access each other with this class as a common friend.\n */\nclass w_raw_access\n{\npublic:\n    /**\n     * @brief create an instance of `T` with given raw pointer.\n     * @param p_raw_ptr raw pointer that `T` wraps or accepts.\n     * @param p_args    custom extended args.\n     */\n    template <typename T, typename RawT, typename ...Args>\n    static auto from_raw(RawT* p_raw_ptr, Args&& ...p_args)\n    {\n        return T(w_raw_tag{}, p_raw_ptr, std::forward<Args>(p_args)...);\n    }\n\n    /**\n     * @brief get raw pointer wrapped in the given wrapper object.\n     * @param p_obj wrapper object.\n     */\n    template <typename T>\n    static auto raw(T& p_obj) noexcept\n    {\n        return p_obj.raw();\n    }\n\n    /**\n     * @brief get the underlying raw pointer from given object,\n     *        and make the object no longer point to that raw resource without releasing it.\n     * @param p_obj the wrapper object to discard its underlying raw pointer.\n     */\n    template <typename T>\n    static auto disown_raw(T&& p_obj) noexcept\n    {\n        return p_obj.disown_raw();\n    }\n};\n\n}  // namespace wolf::media::gst::internal\n"
  },
  {
    "path": "wolf/media/gst/internal/w_utils.cpp",
    "content": "#include \"media/gst/internal/w_utils.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/internal/w_utils.hpp",
    "content": "#pragma once\n\n#include <utility>\n\nnamespace wolf::media::gst::internal {\n\n/**\n * @brief The famous overloaded pattern to overload several callables, e.g. lambdas.\n *\n * reference: https://www.cppstories.com/2019/02/2lines3featuresoverload.html/\n */\ntemplate <typename ...Fs>\nstruct w_overloaded : Fs... { using Fs::operator()...; };\n\ntemplate <typename ...Fs>\nw_overloaded(Fs...) -> w_overloaded<Fs...>;\n\n/**\n * @brief a helper tool used with `overloaded` and `std::visit` to\n *        behave similar to `default` clause in switch/case statements.\n *\n * it is implicitly convertible from anything, but discards them,\n * thus in an overload set, it will be the least match, thus if any other\n * callable wouldn't match, this one will be used.\n *\n * example:\n * ```cpp\n * std::visit(\n *   w_overloaded{\n *     [](int num) { ... case int ... },\n *     [](char* str) { ... case c-string ... },\n *     [](w_blackhole) { ... default ... }\n *   },\n *   my_varaint\n * );\n * ```\n */\nstruct w_blackhole\n{\n    template <typename ...Ts>\n    constexpr w_blackhole(Ts&& ...) noexcept {}\n};\n\n/**\n * @brief make an instantiable callable type out of\n *        a compile-time function pointer.\n *\n * @tparam FV a function symbole/pointer.\n */\ntemplate <auto FV>\nclass w_functor {\npublic:\n    template <typename ...Args>\n    auto operator()(Args&& ...p_args) const\n    {\n        return FV(std::forward<Args>(p_args)...);\n    }\n};\n\n}  // namespace wolf::media::gst::internal\n"
  },
  {
    "path": "wolf/media/gst/internal/w_wrapper.cpp",
    "content": "#include \"media/gst/internal/w_wrapper.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/internal/w_wrapper.hpp",
    "content": "#pragma once\n\n#include \"media/gst/internal/w_common.hpp\"\n#include \"media/gst/internal/w_utils.hpp\"\n#include \"media/gst/core/w_nonowning.hpp\"\n\n#include <memory>\n#include <utility>\n\nnamespace wolf::media::gst {\n\n/**\n * the w_wrapper is helper CRTP class wrapping given raw C type pointer,\n * managing its lifetime and ownership/parentship.\n *\n * @tparam DerivedT class type inheriting this w_wrapper.\n * @tparam RawT     raw type to wrap.\n * @tparam BaseT    base type of `RawT`, for GObject types. (not supported yet, use `void`)\n * @tparam FreeFV   function (pointer) to free the `RawT` pointed resource.\n * @tparam CopyFV   optional function (pointer) to copy the `RawT` pointed resource.\n *                  (default: nullptr)\n */\ntemplate <typename DerivedT,\n          typename RawT,\n          typename BaseT = void,\n          auto FreeFV = nullptr,\n          auto CopyFV = nullptr>\nclass w_wrapper\n{\n    static_assert(\n        std::is_same_v<BaseT, void>,\n        \"currently wrapper base isn't supported. it must be void.\"\n    );\n\n    friend class internal::w_raw_access;\n\n    using underlying_type = std::remove_cvref_t<RawT>;\n\npublic:\n    w_wrapper(const w_wrapper& p_other)\n        requires (CopyFV != nullptr)\n        : _ptr(CopyFV(p_other._ptr.get()))\n        , _parented(false)\n    {}\n\n    w_wrapper(w_wrapper&&) noexcept = default;\n\n    w_wrapper& operator=(const w_wrapper& p_other)\n        requires (CopyFV != nullptr)\n    {\n        reset(CopyFV(p_other._ptr.get()));\n        _parented = false;\n        return *this;\n    }\n\n    w_wrapper& operator=(w_wrapper&&) noexcept = default;\n\n    ~w_wrapper() noexcept\n    {\n        // avoid being passed to FreeFV if it's parented,\n        // as its parent should/will take care of its lifetime.\n        if (_parented) {\n            _ptr.release();\n        }\n    }\n\n    /**\n     * create a nonowning/shallow copy of the instance wrapping\n     * underlying raw pointer.\n     *\n     * only for lvalues, no accidental disposal\n     * of rvalues leading dangling references.\n     *\n     * @return a non-owning shallow copy of the instance.\n     */\n    auto nonowning_view() & -> w_nonowning<DerivedT>\n    {\n        return internal::w_raw_access::from_raw<w_nonowning<DerivedT>>(_ptr.get());\n    }\n\n    /**\n     * set as parented to keep the raw pointer pointing to resource,\n     * but not to try to release it at destruction as that'd be up\n     * to the parent.\n     *\n     * only applicable to lvalues since calling it\n     * on rvalues has a high chance of memory/resource leak,\n     * and it's advised to call this method after\n     * adoption by parent object.\n     */\n    void parented() &\n    {\n        _parented = true;\n    }\n\nprotected:\n    // only derived classes should be able to initialize this class\n    // with thier raw pointer provided resource.\n    explicit w_wrapper(underlying_type* ptr) : _ptr(ptr) {}\n\n    [[nodiscard]] underlying_type* raw() noexcept { return _ptr.get(); }\n    [[nodiscard]] const underlying_type* raw() const noexcept { return _ptr.get(); }\n\n    void replace_raw(underlying_type* ptr = nullptr) { _ptr.reset(ptr); }\n\n    auto disown_raw() noexcept { return _ptr.release(); }\n\nprivate:\n    bool _parented = false;\n    std::unique_ptr<underlying_type, internal::w_functor<FreeFV>> _ptr;\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/video/w_video_format.cpp",
    "content": "#include \"media/gst/video/w_video_format.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/video/w_video_format.hpp",
    "content": "#pragma once\n\n#include <gst/video/video-format.h>\n\nnamespace wolf::media::gst {\n\n/**\n * enum same as GstVideoFormat.\n */\nenum class w_video_format\n{\n    RGB = GST_VIDEO_FORMAT_RGB,\n    RGBx = GST_VIDEO_FORMAT_RGBx,\n    BGR = GST_VIDEO_FORMAT_BGR,\n    BGRx = GST_VIDEO_FORMAT_BGRx\n    // ...\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/video/w_video_info.cpp",
    "content": "#include \"media/gst/video/w_video_info.hpp\"\n\nnamespace wolf::media::gst {\n\nauto w_video_info::make(w_video_format p_format, size_t p_width, size_t p_height)\n    -> boost::leaf::result<w_video_info>\n{\n    auto video_info_raw = gst_video_info_new();\n    if (!video_info_raw) {\n        return W_FAILURE(std::errc::operation_canceled, \"couldn't create video info.\");\n    }\n\n    bool res = gst_video_info_set_format(\n                video_info_raw,\n                static_cast<GstVideoFormat>(p_format),\n                gsl::narrow_cast<guint>(p_width),\n                gsl::narrow_cast<guint>(p_height)\n                );\n    if (!res) {\n        return W_FAILURE(std::errc::operation_canceled, \"couldn't set video info.\");\n    }\n\n    return w_video_info(internal::w_raw_tag{}, video_info_raw);\n}\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/video/w_video_info.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include \"media/gst/internal/w_common.hpp\"\n#include \"media/gst/internal/w_wrapper.hpp\"\n#include \"media/gst/video/w_video_format.hpp\"\n#include \"media/gst/core/w_caps.hpp\"\n\n#include <gst/video/video-info.h>\n\n#include <stdexcept>\n#include <utility>\n\nnamespace wolf::media::gst {\n\n/**\n * wrapper of GstAudioInfo.\n */\nclass w_video_info : public w_wrapper<w_video_info, GstVideoInfo, void, gst_video_info_free>\n{\n    friend class internal::w_raw_access;\n\npublic:\n    /**\n     * @brief make an w_video_info instance with given format and other info.\n     * @return a constructed audio info on success.\n     */\n    [[nodiscard]] static auto make(w_video_format p_format,\n                                   std::size_t p_width,\n                                   std::size_t p_height)\n        -> boost::leaf::result<w_video_info>;\n\n    /**\n     * @brief make an equivalent w_caps instance from this audio info.\n     */\n    w_caps to_caps()\n    {\n        auto ptr = gst_video_info_to_caps(raw());\n        return internal::w_raw_access::from_raw<w_caps>(ptr);\n    }\n\n    /**\n     * @brief set playback fps.\n     * @param p_fps frame per second.\n     */\n    void set_fps(std::size_t p_fps)\n    {\n        raw()->fps_n = 1;\n        raw()->fps_d = gsl::narrow_cast<gint>(p_fps);\n    }\n\n    /**\n     * @brief set playback fps in relative fraction.\n     */\n    void set_fps(std::size_t p_numerator, std::size_t p_denomirator)\n    {\n        raw()->fps_n = gsl::narrow_cast<gint>(p_numerator);\n        raw()->fps_d = gsl::narrow_cast<gint>(p_denomirator);\n    }\n\nprivate:\n    w_video_info(internal::w_raw_tag, GstVideoInfo* video_info_raw) noexcept\n        : w_wrapper(video_info_raw)\n    {}\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/w_application.cpp",
    "content": "#include \"media/gst/w_application.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/w_application.hpp",
    "content": "#pragma once\n\n#include <gst/gst.h>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief a gstreamer application.\n */\nclass w_application\n{\npublic:\n    w_application() = delete;\n\n    static bool init(int* argc, char*** argv)\n    {\n        gst_init(argc, argv);\n        return true;\n    }\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/gst/w_flow.cpp",
    "content": "#include \"media/gst/w_flow.hpp\"\n"
  },
  {
    "path": "wolf/media/gst/w_flow.hpp",
    "content": "#pragma once\n\n#include \"media/gst/core/w_refptr.hpp\"\n#include \"media/gst/core/w_element.hpp\"\n\n#include <vector>\n#include <memory>\n#include <utility>\n\nnamespace wolf::media::gst {\n\n/**\n * @brief a container of w_refptr<w_element> representing a path in a pipeline flow.\n *\n * this container will always contain 2 elements at least.\n *\n * @note this container does not link\n *       or check for correct src/sink composition.\n *       it's only a storage.\n */\nclass w_flow_path\n{\npublic:\n    /**\n     * @brief make a flow path.\n     * @param elements list of elements to make a flow path from.\n     */\n    template <typename ...Ts>\n        requires (sizeof...(Ts) >= 2)\n    static auto make(Ts&& ...elements) {\n        auto path = w_flow_path();\n\n        path._vec.reserve(sizeof...(Ts));\n        (..., path._vec.emplace_back(to_refptr(std::forward<Ts>(elements))));\n\n        return path;\n    }\n\n    constexpr auto size() const noexcept -> std::size_t { return _vec.size(); }\n\n    auto& first() { return _vec[0]; }\n    const auto& first() const { return _vec[0]; }\n\n    auto& last() { return _vec[size() - 1]; }\n    const auto& last() const { return _vec[size() - 1]; }\n\n    auto begin() noexcept { return std::begin(_vec); }\n    auto begin() const noexcept { return std::begin(_vec); }\n\n    auto end() noexcept { return std::end(_vec); }\n    auto end() const noexcept { return std::end(_vec); }\n\n    auto& operator[](std::size_t index) { return _vec[index]; }\n    const auto& operator[](std::size_t index) const { return _vec[index]; }\n\nprivate:\n    w_flow_path() {}\n\n    std::vector<w_refptr<w_element>> _vec;\n};\n\n}  // namespace wolf::media::gst\n"
  },
  {
    "path": "wolf/media/test/avframe.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_MEDIA_FFMPEG) && defined(WOLF_MEDIA_STB)\n\n#include <system/w_leak_detector.hpp>\n#include <boost/test/included/unit_test.hpp>\n\n#include <media/ffmpeg/w_av_frame.hpp>\n#include <media/ffmpeg/w_av_packet.hpp>\n\nBOOST_AUTO_TEST_CASE(avframe_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'avframe_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        using w_av_frame = wolf::media::ffmpeg::w_av_frame;\n        using w_av_config = wolf::media::ffmpeg::w_av_config;\n\n        // create av frame from img\n        const std::filesystem::path path =\n            std::filesystem::current_path().append(\"../../content/texture/rgb.png\");\n\n        BOOST_LEAF_AUTO(_src_frame, w_av_frame::load_video_frame_from_img_file(\n                                        path, AVPixelFormat::AV_PIX_FMT_RGBA));\n\n        const auto _config = _src_frame.get_config();\n\n        auto _dst_config =\n            w_av_config(AVPixelFormat::AV_PIX_FMT_BGRA, _config.width, _config.height);\n        BOOST_LEAF_AUTO(_dst_frame, _src_frame.convert_video(std::move(_dst_config)));\n\n        const std::filesystem::path _new_path = std::filesystem::current_path().append(\"/rgb_converted.png\");\n        BOOST_LEAF_CHECK(_dst_frame.save_video_frame_to_img_file(_new_path));\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"avframe_test got an error: {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] { BOOST_ERROR(\"avframe_test got an error!\"); });\n\n  std::cout << \"leaving test case 'avframe_test'\" << std::endl;\n}\n\n#endif"
  },
  {
    "path": "wolf/media/test/ffmpeg.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_MEDIA_FFMPEG) && defined(WOLF_MEDIA_STB)\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n\n#include <media/ffmpeg/w_ffmpeg.hpp>\n#include <media/ffmpeg/w_encoder.hpp>\n\nusing w_av_frame = wolf::media::ffmpeg::w_av_frame;\nusing w_av_codec_opt = wolf::media::ffmpeg::w_av_codec_opt;\nusing w_av_config = wolf::media::ffmpeg::w_av_config;\nusing w_av_set_opt = wolf::media::ffmpeg::w_av_set_opt;\nusing w_av_packet = wolf::media::ffmpeg::w_av_packet;\nusing w_ffmpeg = wolf::media::ffmpeg::w_ffmpeg;\n\nstatic boost::leaf::result<std::tuple<w_av_packet, w_av_config, w_av_config>> s_encode(\n    _In_ const std::string &p_name, _In_ std::variant<const char *, AVCodecID> &p_codec_id,\n    _In_ const w_av_codec_opt &p_codec_options,\n    _In_ const std::vector<w_av_set_opt> &p_av_set_options, _In_ const bool p_flush = true) {\n  // namespaces\n  using w_encoder = wolf::media::ffmpeg::w_encoder;\n\n  // create av frame from img\n  const auto _img_file_name = std::string(\"../../content/texture/rgb.png\");\n  const std::filesystem::path _img_path = std::filesystem::current_path().append(_img_file_name);\n\n  BOOST_LEAF_AUTO(_src_frame, w_av_frame::load_video_frame_from_img_file(\n                                  _img_path, AVPixelFormat::AV_PIX_FMT_RGBA));\n\n  // source & destination configs\n  const auto _src_config = _src_frame.get_config();\n  auto _dst_config =\n      w_av_config(AVPixelFormat::AV_PIX_FMT_YUV420P, _src_config.width, _src_config.height);\n\n  // encode frame to packet\n  boost::leaf::result<w_encoder> _encoder_res;\n  if (p_codec_id.index() == 0) {\n    auto _codec_id = std::get<0>(p_codec_id);\n    _encoder_res =\n        w_ffmpeg::create_encoder(_dst_config, _codec_id, p_codec_options, p_av_set_options);\n  } else {\n    const auto _codec_id = std::get<1>(p_codec_id);\n    _encoder_res =\n        w_ffmpeg::create_encoder(_dst_config, _codec_id, p_codec_options, p_av_set_options);\n  }\n  // check encoder\n  BOOST_LEAF_AUTO(_encoder, std::move(_encoder_res));\n\n  // convert source frame to yuv frame\n  auto _dst_config_clone = w_av_config(_dst_config);\n  BOOST_LEAF_AUTO(_yuv_frame, _src_frame.convert_video(std::move(_dst_config_clone)));\n\n  auto _packet = w_av_packet();\n  BOOST_LEAF_CHECK(_encoder.encode(_yuv_frame, _packet, p_flush));\n\n  const std::filesystem::path _encoded_path =\n      std::filesystem::current_path().append(wolf::format(\"/{}_yuv_encoded.png\", p_name));\n  BOOST_LEAF_CHECK(_yuv_frame.save_video_frame_to_img_file(_encoded_path));\n\n  return std::make_tuple(std::move(_packet), _src_config, _dst_config);\n}\n\nstatic boost::leaf::result<void> s_decode(\n    _In_ std::tuple<w_av_packet, w_av_config, w_av_config> &p_encoded_tuple,\n    _In_ const std::string &p_name, _In_ std::variant<const char *, AVCodecID> &p_codec_id,\n    _In_ const w_av_codec_opt &p_codec_options,\n    _In_ const std::vector<w_av_set_opt> &p_av_set_options, _In_ const bool p_flush = false) {\n  using w_decoder = wolf::media::ffmpeg::w_decoder;\n\n  // create destination avframe for decoder\n  auto _video_buffer = std::vector<uint8_t>();\n  auto _decoded_frame = w_av_frame(std::forward<w_av_config &&>(std::get<2>(p_encoded_tuple)));\n  BOOST_LEAF_CHECK(_decoded_frame.init());\n  BOOST_LEAF_CHECK(_decoded_frame.set_video_frame(std::move(_video_buffer)));\n\n  // create a decoder\n  boost::leaf::result<w_decoder> _decoder_res;\n  if (p_codec_id.index() == 0) {\n    auto _codec_id = std::get<0>(p_codec_id);\n    _decoder_res = w_ffmpeg::create_decoder(_decoded_frame.get_config(), _codec_id, p_codec_options,\n                                            p_av_set_options);\n  } else {\n    const auto _codec_id = std::get<1>(p_codec_id);\n    _decoder_res = w_ffmpeg::create_decoder(_decoded_frame.get_config(), _codec_id, p_codec_options,\n                                            p_av_set_options);\n  }\n\n  // check decoder\n  BOOST_LEAF_AUTO(_decoder, std::move(_decoder_res));\n\n  // decode the packet\n  BOOST_LEAF_CHECK(_decoder.decode(std::get<0>(p_encoded_tuple), _decoded_frame, p_flush));\n\n  BOOST_LEAF_AUTO(_final_frame, _decoded_frame.convert_video(\n                                    std::forward<w_av_config &&>(std::get<1>(p_encoded_tuple))));\n\n  const std::filesystem::path _path =\n      std::filesystem::current_path().append(wolf::format(\"/{}_rgb_decoded.png\", p_name));\n  BOOST_LEAF_CHECK(_decoded_frame.save_video_frame_to_img_file(_path));\n\n  return {};\n}\n\nBOOST_AUTO_TEST_CASE(av1_encode_decode_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  constexpr auto _name = \"av1\";\n  std::cout << \"entering test case '_encode_decode_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        const auto _codec_opt = w_av_codec_opt{\n            4'000'000, /*bitrate*/\n            60,        /*fps*/\n            600,       /*gop*/\n            -1,        /*level*/\n            2,         /*max_b_frames*/\n            3,         /*refs*/\n            -1,        /*thread_count*/\n        };\n\n        // for more info read https://trac.ffmpeg.org/wiki/Encode/AV1\n        const auto _opts = std::vector<w_av_set_opt>{\n            w_av_set_opt{\"preset\", 12},\n            w_av_set_opt{\"crf\", 50},\n        };\n\n        std::variant<const char *, AVCodecID> _encode_codec_id(\"libsvtav1\");\n        BOOST_LEAF_AUTO(_encoded_tuple, s_encode(_name, _encode_codec_id, _codec_opt, _opts));\n\n        std::variant<const char *, AVCodecID> _decode_codec_id(\"libdav1d\");\n        BOOST_LEAF_CHECK(s_decode(_encoded_tuple, _name, _decode_codec_id, _codec_opt, {}));\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"got error: {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] {\n        const auto _msg = wolf::format(\"got an error\");\n        BOOST_ERROR(_msg);\n      });\n\n  std::cout << \"leaving test case 'av1_encode_decode_test'\" << std::endl;\n}\n\nBOOST_AUTO_TEST_CASE(vp9_encode_decode_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  constexpr auto _name = \"vp9\";\n  std::cout << \"entering test case 'vp9_encode_decode_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        const auto _codec_opt = w_av_codec_opt{\n            4'000'000, /*bitrate*/\n            60,        /*fps*/\n            600,       /*gop*/\n            -1,        /*level*/\n            2,         /*max_b_frames*/\n            3,         /*refs*/\n            -1,        /*thread_count*/\n        };\n\n        // for more info read https://trac.ffmpeg.org/wiki/Encode/VP9\n        const auto _opts = std::vector<w_av_set_opt>();\n\n        std::variant<const char *, AVCodecID> _codec_id(AVCodecID::AV_CODEC_ID_VP9);\n        BOOST_LEAF_AUTO(_encoded_tuple, s_encode(_name, _codec_id, _codec_opt, _opts));\n\n        BOOST_LEAF_CHECK(s_decode(_encoded_tuple, _name, _codec_id, _codec_opt, {}));\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"got error: {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] {\n        const auto _msg = wolf::format(\"got an error\");\n        BOOST_ERROR(_msg);\n      });\n\n  std::cout << \"leaving test case 'vp9_encode_decode_test'\" << std::endl;\n}\n\nBOOST_AUTO_TEST_CASE(x264_encode_decode_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  constexpr auto _name = \"x264\";\n  std::cout << \"entering test case 'x264_encode_decode_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        const auto _codec_opt = w_av_codec_opt{\n            4'000'000, /*bitrate*/\n            60,        /*fps*/\n            600,       /*gop*/\n            -1,        /*level*/\n            2,         /*max_b_frames*/\n            3,         /*refs*/\n            -1,        /*thread_count*/\n        };\n\n        // for more info read https://trac.ffmpeg.org/wiki/Encode/H.264\n        const auto _opts = std::vector<w_av_set_opt>{\n            w_av_set_opt{\"profile\", \"main\"}, w_av_set_opt{\"preset\", \"veryfast\"},\n            w_av_set_opt{\"tune\", \"zerolatency\"}, w_av_set_opt{\"crf\", 22}};\n\n        std::variant<const char *, AVCodecID> _codec_id(AVCodecID::AV_CODEC_ID_H264);\n        BOOST_LEAF_AUTO(_encoded_tuple, s_encode(_name, _codec_id, _codec_opt, _opts));\n\n        BOOST_LEAF_CHECK(s_decode(_encoded_tuple, _name, _codec_id, _codec_opt, {}, true));\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"got error: {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] {\n        const auto _msg = wolf::format(\"got an error\");\n        BOOST_ERROR(_msg);\n      });\n\n  std::cout << \"leaving test case 'x264_encode_decode_test'\" << std::endl;\n}\n\n#endif"
  },
  {
    "path": "wolf/media/test/gstreamer.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_MEDIA_GSTREAMER)\n\n#pragma once\n\n#include <system/w_leak_detector.hpp>\n#include <boost/test/included/unit_test.hpp>\n\n#include <media/gst/w_application.hpp>\n#include <media/gst/core/w_refptr.hpp>\n#include <media/gst/core/w_buffer.hpp>\n#include <media/gst/core/w_mainloop.hpp>\n#include <media/gst/core/w_pipeline.hpp>\n#include <media/gst/core/w_element_factory.hpp>\n#include <media/gst/video/w_video_info.hpp>\n#include <media/gst/video/w_video_format.hpp>\n#include <media/gst/elements/w_element_appsrc.hpp>\n\n#include <thread>\n\nBOOST_AUTO_TEST_CASE(gstreamer_wrapper) {\n    namespace gst = wolf::media::gst;\n\n    boost::leaf::try_handle_all(\n        []() -> boost::leaf::result<void> {\n            gst::w_application::init(nullptr, nullptr);\n\n            std::size_t width = 640;\n            std::size_t height = 480;\n\n            BOOST_LEAF_AUTO(video_info,\n                    gst::w_video_info::make(gst::w_video_format::RGBx, width, height));\n            auto video_caps = video_info.to_caps();\n\n            BOOST_LEAF_AUTO(pipeline, gst::w_pipeline::make(\"main\"));\n            BOOST_LEAF_AUTO(mainloop, gst::w_mainloop::make());\n\n            BOOST_LEAF_AUTO(appsrc, gst::w_element_appsrc::make());\n            auto appsrc_ref = gst::to_refptr(std::move(appsrc));\n            appsrc_ref->set_caps(video_caps);\n            appsrc_ref->set_format(gst::w_format::Time);\n\n            auto push_data = [&appsrc_ref, width, height, frames=0]() mutable {\n                auto buffer = gst::w_buffer::make(width * height * 4);\n                if (!buffer) {\n                    return;\n                }\n\n                //buffer->set_timestamp(appsrc_ref->clock()->get_time());\n                buffer->set_duration(double(frames) / 120.0 * 1e9);\n\n                {\n                    // make sure buffer_map doesn't outlive buffer.\n                    auto data_map = buffer->map_data_write();\n                    auto data = data_map->data();\n                    for (std::size_t y = 0; y < height; ++y) {\n                        for (std::size_t x = 0; x < width; ++x) {\n                            // a simple SDF rendering. a square in middle,\n                            // and a circle of same size passing through diagonally.\n                            const auto ratio = double(width) / height;\n                            const auto t = double(frames % 120) / 120 - 0.5;\n                            const auto u = (double(x) / width - 0.5) * ratio;\n                            const auto v = double(y) / height - 0.5;\n\n                            const auto square = std::max(std::abs(u), std::abs(v)) - 0.2;\n                            const auto circle = std::sqrt(std::pow(u - t, 2) + std::pow(v - t, 2)) - 0.2;\n\n                            data[y * width * 4 + x * 4 + 0] = (square < 0) * 255;\n                            data[y * width * 4 + x * 4 + 1] = (circle < 0) * 255;\n                            data[y * width * 4 + x * 4 + 2] = 0;\n                            data[y * width * 4 + x * 4 + 3] = 0;\n                        }\n                    }\n                }\n\n                appsrc_ref->emit_push_buffer(std::move(*buffer));\n\n                frames = (frames + 1) % 120;\n            };\n\n            std::size_t sourceid = 0;\n            appsrc_ref->hook_need_data([&](auto /* length */) {\n                if (sourceid) return;\n                sourceid = mainloop.idle_add(push_data);\n            });\n            appsrc_ref->hook_enough_data([&] {\n                mainloop.idle_remove(sourceid);\n                sourceid = 0;\n            });\n\n            BOOST_LEAF_AUTO(test_video_src,\n                    gst::w_element_factory::make_simple(\"videotestsrc\", \"src\"));\n            BOOST_LEAF_AUTO(video_convert,\n                    gst::w_element_factory::make_simple(\"videoconvert\", \"video_convert\"));\n            BOOST_LEAF_AUTO(auto_video_sink,\n                    gst::w_element_factory::make_simple(\"autovideosink\", \"sink\"));\n\n            auto flow = gst::w_flow_path::make(\n                appsrc_ref,\n                std::move(video_convert),\n                std::move(auto_video_sink)\n            );\n\n            BOOST_REQUIRE(pipeline.bin(flow));\n            BOOST_REQUIRE(pipeline.link(flow));\n\n            BOOST_REQUIRE(pipeline.play());\n\n            auto timer = std::jthread([&mainloop, &pipeline]() {\n                for (int i = 1; i <= 5; ++i) {\n                    std::this_thread::sleep_for(std::chrono::seconds(1));\n                }\n                pipeline.stop();\n                mainloop.stop();\n            });\n\n            mainloop.run();\n\n            return {};\n        },\n        [](const w_trace &p_trace) {\n          BOOST_ERROR(wolf::format(\"got error: {}\", p_trace.to_string()));\n        },\n        [] {\n          BOOST_ERROR(wolf::format(\"got an error\"));\n        }\n    );\n}\n\n#endif  // defined(WOLF_TEST) && defined(WOLF_MEDIA_GSTREAMER)\n"
  },
  {
    "path": "wolf/media/test/image.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_MEDIA_STB)\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n\n#include <media/w_image.hpp>\n\nBOOST_AUTO_TEST_CASE(image_load_save_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'image_load_save_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        using w_image = wolf::media::w_image;\n        using w_image_data = wolf::media::w_image_data;\n\n        const auto &_rgb_file = std::filesystem::current_path().append(\"../../content/texture/rgb.png\");\n        auto _src_image_res = w_image::load(_rgb_file, 0);\n        // POOYA: don't use BOOST_LEAF_AUTO because CodeCov might break\n        if (!_src_image_res.has_error()) {\n          BOOST_LEAF_AUTO(_src_image, std::move(_src_image_res));\n          const auto &_bmp_path = std::filesystem::current_path().append(\"/rgb_bmp.png\");\n          BOOST_LEAF_CHECK(w_image::save_bmp(_bmp_path, _src_image));\n\n          constexpr auto _quality = 90;\n          const auto &_jpg_path = std::filesystem::current_path().append(\"/rgb_jpg.png\");\n          BOOST_LEAF_CHECK(w_image::save_jpg(_jpg_path, _src_image, _quality));\n        }\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"got error: {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] {\n        const auto _msg = wolf::format(\"got an error\");\n        BOOST_ERROR(_msg);\n      });\n\n  std::cout << \"leaving test case 'image_load_save_test'\" << std::endl;\n}\n\n#endif"
  },
  {
    "path": "wolf/media/test/openal.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_MEDIA_OPENAL)\n\n#pragma once\n\n#include <system/w_leak_detector.hpp>\n#include <boost/test/included/unit_test.hpp>\n\n#include <media/w_openal.hpp>\n\nBOOST_AUTO_TEST_CASE(openal_play_wav) {\n  using wolf::media::w_openal;\n  using wolf::media::w_openal_config;\n\n  const wolf::system::w_leak_detector _detector = {};\n\n  // TODO (pooya: openAL has memoy leak https://github.com/kcat/openal-soft/issues/782)\n  auto a = w_openal();\n  a.init(w_openal_config{});\n\n  auto _current_dir = std::filesystem::current_path().append(\"../../content/audio/sine.wav\");\n  std::cout << _current_dir.string();\n\n  BOOST_REQUIRE(std::filesystem::exists(_current_dir) == true);\n\n  // let file_name = \"sine.wav\";\n  // let wolf_dir = current_dir.join(\"wolf\");\n  // let file_path = if wolf_dir.exists() { wolf_dir.join(file_name) }\n  // else {current_dir.join(file_name)};\n\n  // make sure constructor works. later update with wav header.\n  // auto openal = w_openal{\n  //  w_openal_config{\n  //    .format = AL_FORMAT_STEREO16,\n  //    .sample_rate = 48000,\n  //    .channels = 1\n  //  }\n  //};\n}\n\n#endif\n"
  },
  {
    "path": "wolf/media/w_image.cpp",
    "content": "#ifdef WOLF_MEDIA_STB\n\n#include \"w_image.hpp\"\n\n#define STB_IMAGE_IMPLEMENTATION\n#include <stb_image.h>\n\n#define STB_IMAGE_WRITE_IMPLEMENTATION\n#include <stb_image_write.h>\n\n#pragma region w_image_data\n\nusing w_image_data = wolf::media::w_image_data;\n\nw_image_data::w_image_data(w_image_data &&p_other) noexcept {\n  _move(std::move(p_other));\n}\n\n// move assignment operator.\nw_image_data &w_image_data::operator=(w_image_data &&p_other) noexcept {\n  _move(std::move(p_other));\n  return *this;\n}\n\nw_image_data::~w_image_data() noexcept {\n  this->width = 0;\n  this->height = 0;\n  this->comp = 0;\n  if (this->raw_data != nullptr) {\n    stbi_image_free(this->raw_data);\n    this->raw_data = nullptr;\n  }\n}\n\nvoid w_image_data::_move(w_image_data &&p_other) noexcept {\n  this->width = p_other.width;\n  this->height = p_other.height;\n  this->comp = p_other.comp;\n  this->raw_data = std::exchange(p_other.raw_data, nullptr);\n}\n\n#pragma endregion\n\nusing w_image = wolf::media::w_image;\n\nboost::leaf::result<w_image_data>\nw_image::load(_In_ const std::filesystem::path &p_path,\n              int p_requested_component) {\n  if (p_path.empty()) {\n    return W_FAILURE(std::errc::invalid_argument, \"could not load image\");\n  }\n\n  const auto _path_str = p_path.string();\n\n  w_image_data _data = {};\n  _data.raw_data = stbi_load(_path_str.c_str(), &_data.width, &_data.height,\n                             &_data.comp, p_requested_component);\n  if (_data.raw_data == nullptr) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"could not load image from file: \" + _path_str);\n  }\n\n  return _data;\n}\n\nboost::leaf::result<int>\nw_image::save_bmp(_In_ const std::filesystem::path &p_path,\n                  _In_ const w_image_data &p_image_data) {\n  if (p_path.empty() || !std::filesystem::exists(p_path.parent_path())) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"could not save bmp file to the following path: \" +\n                         p_path.string());\n  }\n  return stbi_write_bmp(p_path.string().c_str(), p_image_data.width,\n                        p_image_data.height, p_image_data.comp,\n                        p_image_data.raw_data);\n}\n\nboost::leaf::result<int>\nw_image::save_hdr(_In_ const std::filesystem::path &p_path,\n                  _In_ const gsl::span<float> p_data, _In_ uint32_t p_width,\n                  _In_ uint32_t p_height, _In_ uint32_t p_comp) {\n\n  if (p_path.empty() || !std::filesystem::exists(p_path.parent_path())) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"could not save hdr file to the the following path: \" +\n                         p_path.string());\n  }\n  return stbi_write_hdr(p_path.string().c_str(), \n    gsl::narrow_cast<int>(p_width), \n    gsl::narrow_cast<int>(p_height), \n    gsl::narrow_cast<int>(p_comp),\n                        p_data.data());\n}\n\nboost::leaf::result<int>\nw_image::save_jpg(_In_ const std::filesystem::path &p_path,\n                  _In_ const w_image_data &p_image_data,\n                  _In_ uint32_t p_quality) {\n  if (p_path.empty() || !std::filesystem::exists(p_path.parent_path())) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"could not save jpg file to the following path: \" +\n                         p_path.string());\n  }\n  return stbi_write_jpg(p_path.string().c_str(), p_image_data.width,\n                        p_image_data.height, p_image_data.comp,\n                        p_image_data.raw_data, gsl::narrow_cast<int>(p_quality));\n}\n\nboost::leaf::result<int>\nw_image::save_png(_In_ const std::filesystem::path &p_path,\n                  _In_ const w_image_data &p_image_data,\n                  _In_ uint32_t p_stride) {\n  if (p_path.empty() || !std::filesystem::exists(p_path.parent_path())) {\n    return W_FAILURE(std::errc::invalid_argument,\n                     \"could not save png file to the following path: \" +\n                         p_path.string());\n  }\n  return stbi_write_png(p_path.string().c_str(), p_image_data.width,\n                        p_image_data.height, p_image_data.comp,\n                        p_image_data.raw_data, gsl::narrow_cast<int>(p_stride));\n}\n\n#endif\n\n\n"
  },
  {
    "path": "wolf/media/w_image.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_STB\n\n#pragma once\n\n#include \"w_image_data.hpp\"\n#include <wolf/wolf.hpp>\n\nnamespace wolf::media {\n\nclass w_image_data {\npublic:\n  // constructor\n  W_API w_image_data() noexcept = default;\n\n  // move constructor\n  W_API w_image_data(w_image_data &&p_other) noexcept;\n\n  // move assignment operator.\n  W_API w_image_data &operator=(w_image_data &&p_other) noexcept;\n\n  // destructor\n  W_API ~w_image_data() noexcept;\n\n  uint8_t *raw_data = nullptr;\n  int width = -1;\n  int height = -1;\n  int comp = -1;\n\nprivate:\n  // copy constructor.\n  w_image_data(const w_image_data &) = delete;\n  // copy assignment operator.\n  w_image_data &operator=(const w_image_data &) = delete;\n\n  // move implementation\n  void _move(w_image_data &&p_other) noexcept;\n};\n\nclass w_image {\npublic:\n  /**\n   * load raw data from image path\n   * p_path, the image path\n   * p_requested_component, the requested component (default value is zero)\n   * returns raw bytes on success as result format\n   */\n  W_API static boost::leaf::result<w_image_data>\n  load(_In_ const std::filesystem::path &p_path, int p_requested_component = 0);\n\n  /**\n   * save raw data in the format of bmp\n   * p_path, the destination path\n   * p_image_data, the image data\n   * returns zero on success as result format\n   */\n  W_API static boost::leaf::result<int>\n  save_bmp(_In_ const std::filesystem::path &p_path,\n           _In_ const w_image_data &p_image_data);\n\n  /**\n   * save raw data in the format of hdr\n   * p_path, the destination path\n   * p_data, the raw data of RGBA\n   * p_width, the width of image\n   * p_height, the height of image\n   * p_comp, the component of image\n   * returns zero on success as result format\n   */\n  W_API static boost::leaf::result<int>\n  save_hdr(_In_ const std::filesystem::path &p_path,\n           _In_ gsl::span<float> p_data, _In_ uint32_t p_width,\n           _In_ uint32_t p_height, _In_ uint32_t p_comp);\n\n  /**\n   * save raw data in the format of jpg\n   * p_path, the destination path\n   * p_image_data, the image data\n   * p_quality, the quality of jpeg (an integer value between 1 and 100.\n        the higher quality looks better but results in a bigger image)\n   * returns zero on success as result format\n   */\n  W_API static boost::leaf::result<int>\n  save_jpg(_In_ const std::filesystem::path &p_path,\n           _In_ const w_image_data &p_image_data, _In_ uint32_t p_quality);\n\n  /**\n   * save raw data in the format of png\n   * p_path, the destination path\n   * p_image_data, the image data\n   * p_stride, the stride of data\n   * returns zero on success as result format\n   */\n  W_API static boost::leaf::result<int>\n  save_png(_In_ const std::filesystem::path &p_path,\n           _In_ const w_image_data &p_image_data, _In_ uint32_t p_stride);\n};\n} // namespace wolf::media\n\n#endif\n"
  },
  {
    "path": "wolf/media/w_image_data.cpp",
    "content": "#ifdef WOLF_MEDIA_STB\n\n#include \"w_image.hpp\"\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#define STB_IMAGE_IMPLEMENTATION\n#include <stb_image.h>\n#include <DISABLE_ANALYSIS_END>\n\nusing w_image_data = wolf::media::w_image_data;\n\nw_image_data::w_image_data(w_image_data &&p_other) noexcept {\n  _move(std::move(p_other));\n}\n\n// move assignment operator.\nw_image_data &w_image_data::operator=(w_image_data &&p_other) noexcept {\n  _move(std::move(p_other));\n  return *this;\n}\n\nw_image_data::~w_image_data() noexcept {\n  this->width = 0;\n  this->height = 0;\n  this->comp = 0;\n  if (this->raw_data != nullptr) {\n    stbi_image_free(this->raw_data);\n    this->raw_data = nullptr;\n  }\n}\n\nvoid w_image_data::_move(w_image_data &&p_other) noexcept {\n  this->width = p_other.width;\n  this->height = p_other.height;\n  this->comp = p_other.comp;\n  this->raw_data = std::exchange(p_other.raw_data, nullptr);\n}\n\n#endif\n\n\n"
  },
  {
    "path": "wolf/media/w_image_data.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_STB\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n\nnamespace wolf::media {} // namespace wolf::media\n\n#endif\n"
  },
  {
    "path": "wolf/media/w_openal.cpp",
    "content": "#ifdef WOLF_MEDIA_OPENAL\n\n#include \"w_openal.hpp\"\n\n#include <iostream>\n\nusing w_openal = wolf::media::w_openal;\nusing w_openal_config = wolf::media::w_openal_config;\n\nALsizei AL_APIENTRY w_openal::s_openal_callback(_In_ void *p_user_ptr,\n                                                _In_ void *p_data,\n                                                _In_ ALsizei p_size) {\n  const auto _openal_nn = gsl::narrow_cast<w_openal *>(p_user_ptr);\n  size_t _bytes = 0;\n\n  auto _read_offset = _openal_nn->_read_pos;\n  while (_bytes < p_size) {\n    /* If the write offset == read offset, there's nothing left in the\n     * ring-buffer. Break from the loop and give what has been written.\n     */\n    const auto _write_offset = _openal_nn->_write_pos;\n    if (_write_offset == _read_offset) {\n      break;\n    }\n\n    // If the write offset is behind the read offset, the readable\n    // portion wrapped around. Just read up to the end of the buffer in\n    // that case, otherwise read up to the write offset. Also limit the\n    // amount to copy given how much is remaining to write.\n    auto _todo = ((_write_offset < _read_offset) ? _openal_nn->_data_size\n                                                 : _write_offset) -\n                 _read_offset;\n    _todo = _todo > (p_size - _bytes) ? (p_size - _bytes) : _todo;\n\n    // copy from the ring buffer to the provided output buffer.\n    // wrap the resulting read offset if it reached the end of the ring-buffer.\n\n    memcpy(p_data, &_openal_nn->_data[_read_offset], _todo);\n    p_data = gsl::narrow_cast<ALbyte *>(p_data) + _todo;\n    _bytes += gsl::narrow_cast<ALsizei>(_todo);\n\n    _read_offset += _todo;\n    if (_read_offset == _openal_nn->_data_size) {\n      _read_offset = 0;\n    }\n  }\n  // finally, store the updated read offset, and return how many bytes have been\n  // written\n  _openal_nn->_read_pos = _read_offset;\n\n  return gsl::narrow_cast<ALsizei>(_bytes);\n}\n\nw_openal::w_openal(w_openal &&p_other) noexcept {\n\n  if (this == &p_other)\n    return;\n\n  _release();\n\n  this->_config = std::move(p_other._config);\n  this->_device = std::exchange(p_other._device, nullptr);\n  this->_ctx = std::exchange(p_other._ctx, nullptr);\n  this->_data = std::exchange(p_other._data, nullptr);\n  this->_data_size = std::exchange(p_other._data_size, 0);\n  this->_read_pos = std::exchange(p_other._read_pos, 0);\n  this->_write_pos = std::exchange(p_other._write_pos, 0);\n  this->_buffer = std::exchange(p_other._buffer, 0);\n  this->_source = std::exchange(p_other._source, 0);\n  this->_start_offset = std::exchange(p_other._start_offset, 0);\n  this->_decoder_offset = std::exchange(p_other._decoder_offset, 0);\n  this->_total_read_bytes = std::exchange(p_other._total_read_bytes, 0);\n  this->_size_of_chunk = std::exchange(p_other._size_of_chunk, 0);\n  this->_callback_ptr = std::exchange(p_other._callback_ptr, nullptr);\n}\n\nw_openal::~w_openal() noexcept { _release(); }\n\n void w_openal::reset() {\n  this->_read_pos = 0;\n  this->_write_pos = 0;\n  this->_decoder_offset = 0;\n  this->_total_read_bytes = 0;\n}\n\nstd::tuple<std::string, std::string> w_openal::get_all_devices() {\n  std::string _input_devices;\n  std::string _output_devices;\n\n  if (alcIsExtensionPresent(nullptr, \"ALC_enumeration_EXT\") == AL_TRUE) {\n    if (alcIsExtensionPresent(nullptr, \"ALC_enumerate_all_EXT\") == AL_TRUE) {\n      _output_devices = alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);\n    } else {\n      _output_devices = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);\n    }\n    _input_devices = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER);\n  }\n\n  return std::make_tuple(_output_devices, _input_devices);\n}\n\nstd::string w_openal::get_last_error() {\n  const auto _error = alGetError();\n  switch (_error) {\n  default:\n    return \"unknown error code\";\n  case AL_NO_ERROR:\n    return \"\";\n  case AL_INVALID_NAME:\n    return \"AL_INVALID_NAME\";\n  case AL_INVALID_ENUM:\n    return \"AL_INVALID_ENUM\";\n  case AL_INVALID_VALUE:\n    return \"AL_INVALID_VALUE\";\n  case AL_INVALID_OPERATION:\n    return \"AL_INVALID_OPERATION\";\n  case AL_OUT_OF_MEMORY:\n    return \"AL_OUT_OF_MEMORY\";\n  }\n}\n\nw_openal_config w_openal::get_config() const { return this->_config; }\n\nboost::leaf::result<int>\nw_openal::init(_In_ const w_openal_config &p_config) noexcept {\n\n  auto _ret = 0;\n  this->_config = p_config;\n\n  DEFER{\n    if (_ret != 0) {\n      _release();\n    }\n  });\n\n  // open and initialize a audio device\n  this->_device = alcOpenDevice(nullptr);\n  if (this->_device == nullptr) {\n    _ret = -1;\n    return W_FAILURE(std::errc::operation_canceled,\n                 \"could not open a openal device\");\n  }\n\n  //this->_ctx = alcCreateContext(this->_device, nullptr);\n  //if (this->_ctx == nullptr || alcMakeContextCurrent(this->_ctx) == ALC_FALSE) {\n  //  _ret = -1;\n  //  return W_FAILURE(std::errc::operation_canceled, \"could not get openal context\");\n  //}\n\n  //// get the sound format, and figure out the OpenAL format\n  //const auto _format = this->_config.format;\n  //const auto _sample_rate = this->_config.sample_rate;\n  //const auto _number_of_channels = this->_config.channels;\n\n  //this->_data = nullptr;\n\n  //switch (_format) {\n  //default:\n  //case AL_FORMAT_MONO16:\n  //case AL_FORMAT_STEREO16: {\n  //  // Signed 16-bit buffer format\n  //  this->_size_of_chunk = sizeof(int16_t);\n  //  break;\n  //}\n  //case AL_FORMAT_MONO8:\n  //case AL_FORMAT_STEREO8: {\n  //  // Unsigned 8-bit buffer format\n  //  this->_size_of_chunk = sizeof(uint8_t);\n  //  break;\n  //}\n  //}\n\n  //// generate the buffer\n  //alGenBuffers(1, &this->_buffer);\n  //auto _error = get_last_error();\n  //if (!_error.empty()) {\n  //  _ret = -1;\n  //  return W_FAILURE(std::errc::operation_canceled,\n  //               \"could not generate buffer for openAL because \" + _error);\n  //}\n\n  //alGenSources(1, &this->_source);\n  //_error = get_last_error();\n  //if (!_error.empty()) {\n  //  _ret = -1;\n  //  return W_FAILURE(std::errc::operation_canceled,\n  //               \"could not generate sources for openAL\");\n  //}\n\n  //if (alIsExtensionPresent(\"AL_SOFTX_callback_buffer\") != 0) {\n  //  _ret = -1;\n  //  return W_FAILURE(std::errc::operation_canceled,\n  //               \"could not get AL_SOFT_callback_buffer\");\n  //}\n\n  //this->_callback_ptr = gsl::narrow_cast<LPALBUFFERCALLBACKSOFT>(\n  //    alGetProcAddress(\"alBufferCallbackSOFT\"));\n  //if (this->_callback_ptr == nullptr) {\n  //  _ret = -1;\n  //  return W_FAILURE(std::errc::operation_canceled,\n  //               \"could not get LPALBUFFERCALLBACKSOFT\");\n  //}\n\n  //alcGetIntegerv(this->_device, ALC_REFRESH, 1, &this->_config.refresh_rate);\n\n  //// set a 1s ring buffer size\n  //this->_data_size =\n  //    gsl::narrow_cast<ALuint>(_sample_rate * _number_of_channels) *\n  //    this->_size_of_chunk * sizeof(float);\n\n  //if (this->_data != nullptr) {\n  //  free(this->_data);\n  //}\n  //this->_data = gsl::narrow_cast<ALbyte *>(calloc(1, this->_data_size));\n  //if (this->_data == nullptr) {\n  //  _ret = -1;\n  //  return W_FAILURE(std::errc::not_enough_memory,\n  //               std::format(\"could not allocate {} byets for openal buffer\",\n  //                           this->_data_size));\n  //}\n  //this->_read_pos = 0;\n  //this->_write_pos = 0;\n  //this->_decoder_offset = 0;\n  //this->_callback_ptr(this->_buffer, _format, _sample_rate, s_openal_callback,\n  //                    this /* send openal object on user's data*/\n  //);\n\n  //alSourcei(this->_source, AL_BUFFER, (ALint)(this->_buffer));\n  //_error = get_last_error();\n  //if (!_error.empty()) {\n  //  _ret = -1;\n  //  return W_FAILURE(std::errc::not_enough_memory,\n  //               \"could not set openal source because \" + _error);\n  //}\n\n  return _ret;\n}\n\nvoid w_openal::_release() noexcept {\n  if (this->_source != 0) {\n    alSourceRewind(this->_source);\n    alSourcei(this->_source, AL_BUFFER, 0);\n    alDeleteSources(1, &this->_source);\n  }\n\n  if (this->_data != nullptr) {\n    free(this->_data);\n    this->_data = nullptr;\n  }\n\n  if (this->_buffer != 0) {\n    alDeleteBuffers(1, &this->_buffer);\n  }\n\n  if (this->_ctx != nullptr) {\n    alcDestroyContext(this->_ctx);\n  }\n  if (this->_device != nullptr) {\n    alcCloseDevice(this->_device);\n    this->_device = nullptr;\n  }\n\n  this->_callback_ptr = nullptr;\n}\n\n#endif\n\n\n"
  },
  {
    "path": "wolf/media/w_openal.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_MEDIA_OPENAL\n\n#pragma once\n\n#include <wolf.hpp>\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#include <AL/al.h>\n#include <AL/alext.h>\n#include <DISABLE_ANALYSIS_END>\n\nnamespace wolf::media {\n\nstruct w_openal_config {\n  // the audio format\n  ALenum format = AL_FORMAT_STEREO16;\n  // sample rate of audio\n  ALsizei sample_rate = 44100;\n  // refresh rate of audio\n  int refresh_rate = 25;\n  // number of channels\n  int channels = 2;\n};\n\nclass w_openal {\npublic:\n  // default constructor\n  W_API w_openal() noexcept = default;\n\n  // move constructor.\n  W_API w_openal(w_openal &&p_other) noexcept;\n  // move assignment operator.\n  W_API w_openal &operator=(w_openal &&p_other) = default;\n\n  // destructor\n  W_API virtual ~w_openal() noexcept;\n\n  /**\n   * initialize the openal\n   * @param p_config, the openal audio\n   * returns zero on success as result format\n   */\n  W_API\n  boost::leaf::result<int>\n  init(_In_ const w_openal_config &p_config) noexcept;\n\n  /**\n   * update the openal\n   * @param p_audio_frame_buffer, the audio frame buffer\n   * @param p_audio_frame_buffer_len, the length of audio frame buffer\n   * @returns zero on success\n   */\n   template <typename T>\n     requires std::is_integral_v<int16_t> || std::is_integral_v<int8_t>\n   W_API boost::leaf::result<int>\n   update(_In_ const T *p_audio_frame_buffer,\n          _In_ const size_t p_audio_frame_buffer_len) {\n     // get state and pos\n     ALenum _state = 0;\n     ALint _pos = 0;\n     alGetSourcei(this->_source, AL_SAMPLE_OFFSET, &_pos);\n     alGetSourcei(this->_source, AL_SOURCE_STATE, &_state);\n\n    const auto _frame_size = this->_config.channels * this->_size_of_chunk;\n    auto _write_offset = this->_write_pos;\n\n    while (this->_total_read_bytes < p_audio_frame_buffer_len) {\n      size_t _read_bytes = 0;\n      const size_t _read_offset = this->_read_pos;\n      if (_read_offset > _write_offset) {\n        /*\n         * Note that the ring buffer's writable space is one byte less\n         * than the available area because the write offset ending up\n         * at the read offset would be interpreted as being empty\n         * instead of full.\n         */\n        auto _writable = _read_offset - _write_offset - 1;\n        if (_writable < _frame_size) {\n          break;\n        }\n\n        _writable = (_writable > p_audio_frame_buffer_len)\n                        ? p_audio_frame_buffer_len\n                        : _writable;\n        std::memcpy(&this->_data[_write_offset], p_audio_frame_buffer,\n                    _frame_size *\n                        gsl::narrow_cast<int>(_writable / _frame_size));\n\n        const auto _num_frames = _writable / _frame_size;\n        if (_num_frames < 1) {\n          break;\n        }\n\n        _read_bytes = _num_frames * _frame_size;\n        _write_offset += _read_bytes;\n\n        this->_total_read_bytes += _read_bytes;\n      } else {\n        /*\n         * If the read offset is at or behind the write offset, the\n         * writeable area (might) wrap around. Make sure the sample\n         * data can fit, and calculate how much can go in front before\n         * wrapping.\n         */\n        auto _writable = !_read_offset ? this->_data_size - _write_offset - 1\n                                       : (this->_data_size - _write_offset);\n        if (_writable < _frame_size) {\n          break;\n        }\n\n        _writable = (_writable > p_audio_frame_buffer_len)\n                        ? p_audio_frame_buffer_len\n                        : _writable;\n\n        std::memcpy(&this->_data[_write_offset], p_audio_frame_buffer,\n                    _frame_size *\n                        gsl::narrow_cast<int>(_writable / _frame_size));\n\n        const auto _num_frames = _writable / _frame_size;\n        if (_num_frames < 1) {\n          break;\n        }\n\n        _read_bytes = _num_frames * _frame_size;\n        _write_offset += _read_bytes;\n        if (_write_offset == this->_data_size) {\n          _write_offset = 0;\n        }\n        this->_total_read_bytes += _read_bytes;\n      }\n      this->_write_pos = _write_offset;\n      this->_decoder_offset += _read_bytes;\n    }\n\n    if (_state != AL_PLAYING && _state != AL_PAUSED) {\n\n      /*\n        if the source is not playing or paused, it either underrun\n        (AL_STOPPED) or is just getting started (AL_INITIAL).\n        if the ring buffer is empty, it's done,\n        otherwise play the source with what's available.\n      */\n      const auto _readable = ((_write_offset >= this->_read_pos)\n                                  ? _write_offset\n                                  : (this->_data_size + _write_offset)) -\n                             this->_read_pos;\n      if (_readable == 0) {\n        return W_FAILURE(std::errc::operation_canceled,\n                     \"no openal data avaiable for reading\");\n      }\n\n      /*\n       * store the playback offset that the source will start reading from,\n       * so it can be tracked during playback.\n       */\n      this->_start_offset = this->_decoder_offset - _readable;\n      alSourcePlay(this->_source);\n\n      auto _error = get_last_error();\n      if (!_error.empty()) {\n        return W_FAILURE(std::errc::operation_canceled,\n                     \"error while updating openal because: \" + _error);\n      }\n    }\n    \n    this->_total_read_bytes = 0;\n    \n    return 0;\n  }\n\n    /**\n     * reset the openal\n     * @returns void\n     */\n    W_API\n    void reset();\n  \n    /**\n     * get openal config\n     * @returns the openal config\n     */\n    W_API\n    w_openal_config get_config() const;\n  \n    /**\n     * returns all output/input devices\n     * @returns output_devices, input_devices\n     */\n    W_API\n    static std::tuple<std::string, std::string> get_all_devices();\n  \n    /**\n     * get the last error\n     * @returns last error of openal\n     */\n    W_API\n    static std::string get_last_error();\n  \n   private:\n    // disable copy constructor\n    w_openal(const w_openal &) = delete;\n    // disable copy operator\n    w_openal &operator=(const w_openal &) = delete;\n\n  static ALsizei AL_APIENTRY s_openal_callback(_In_ void *p_user_ptr,\n                                               _In_ void *p_data,\n                                               _In_ ALsizei p_size);\n  void _release() noexcept;\n\n  w_openal_config _config = {};\n\n  ALCdevice *_device = nullptr;\n  ALCcontext *_ctx = nullptr;\n\n  // a lockless ring-buffer (supports single-provider, single-consumer\n  // operation)\n  ALbyte *_data = nullptr;\n  size_t _data_size = 0;\n  size_t _read_pos = 0;\n  size_t _write_pos = 0;\n\n  // The buffer to get the callback, and source to play with\n  ALuint _buffer = 0;\n  ALuint _source = 0;\n  size_t _start_offset = 0;\n\n  // Handle for the audio file to decode\n  size_t _decoder_offset = 0;\n\n  size_t _total_read_bytes = 0;\n  size_t _size_of_chunk = 0;\n  LPALBUFFERCALLBACKSOFT _callback_ptr = nullptr;\n};\n} // namespace wolf::media\n\n#endif\n\n\n\n"
  },
  {
    "path": "wolf/ml/nudity_detection/w_nudity_detection.cpp",
    "content": "#include \"w_nudity_detection.hpp\"\n\n#include <iostream>\n\n#include <torch/script.h>\n#include <torch/torch.h>\n\n#include \"../w_common.hpp\"\n#include <opencv2/opencv.hpp>\n\nusing w_nud_det = wolf::ml::nudet::w_nud_det;\n\nw_nud_det::w_nud_det(_In_ std::string& nudity_detection_model_path) {\n  _model = torch::jit::load(nudity_detection_model_path);\n  _model.to(torch::kCUDA);\n  _model.eval();\n\n  network_warm_up(get_env_int(\"TEMP_IMAGE_HEIGHT\"), get_env_int(\"TEMP_IMAGE_WIDTH\"));\n}\n\nw_nud_det::~w_nud_det() = default;\n\nauto w_nud_det::nudity_detection(_In_ uint8_t* pImageData, _In_ const int pImageWidth,\n                                 _In_ const int pImageHeight, _In_ const int pImageChannels)\n    -> std::vector<float> {\n  std::vector<float> result;\n\n  // // Put image in tensor\n  // std::vector<uint8_t>\n  // \timage_data;\n  // auto e = std::end(image_data);\n  // const int total = pImageWidth * pImageHeight * pImageChannels;\n  // image_data.insert(e, pImageData, pImageData + total);\n\n  // auto input = cppflow::tensor(image_data, {pImageHeight, pImageWidth, pImageChannels});\n  // input = cppflow::cast(input, TF_UINT8, TF_FLOAT, false);\n  // input = input / 255.f;\n  // input = cppflow::expand_dims(input, 0, static_cast<cppflow::datatype>(3));\n  // auto output = _model(input);\n\n  // result = output.get_data<float>();\n\n  torch::Tensor tensor_image =\n      torch::from_blob(pImageData, {1, pImageHeight, pImageWidth, pImageChannels}, torch::kByte);\n\n  tensor_image = tensor_image.permute({0, 3, 1, 2});\n  tensor_image = tensor_image.toType(torch::kFloat);\n  tensor_image = tensor_image.div(255);\n\n  // Define normalization constants\n  const float kNormalizationMean[] = {0.485f, 0.456f, 0.406f};\n  const float kNormalizationStd[] = {0.229f, 0.224f, 0.225f};\n\n  // Create the normalization transform\n  auto normalization_transform = torch::data::transforms::Normalize<float>(\n      {kNormalizationMean[0], kNormalizationMean[1], kNormalizationMean[2]},\n      {kNormalizationStd[0], kNormalizationStd[1], kNormalizationStd[2]});\n\n  // Apply normalization transform to the image tensor\n  tensor_image = normalization_transform(tensor_image);\n\n  tensor_image = tensor_image.to(torch::kCUDA);\n\n  torch::Tensor output;\n\n  output = _model.forward({tensor_image}).toTensor();\n\n  for (int i = 0; i < output.sizes()[1]; i++) {\n    result.push_back(output[0][i].item<float>());\n  }\n\n  return result;\n}\n\nauto w_nud_det::network_warm_up(_In_ int pHeight, _In_ int pWidth) -> void {\n  for (int i = 0; i < 2; i++) {\n    cv::Mat const temp_image = cv::Mat(cv::Size(pWidth, pHeight), CV_8UC3, cv::Scalar(0, 0, 0));\n    auto result = nudity_detection(temp_image.data, pWidth, pHeight, temp_image.channels());\n  }\n}\n"
  },
  {
    "path": "wolf/ml/nudity_detection/w_nudity_detection.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <iostream>\n\n#include <torch/script.h>\n#include <torch/torch.h>\n\n// #include \"cppflow/cppflow.h\"\n// #include \"dlib_export.h\"\n// #include \"salieri.h\"\n\n#include \"wolf.hpp\"\n\nnamespace wolf::ml::nudet {\n\nclass w_nud_det {\n public:\n  /*!\n          The constructor of the class.\n  */\n  explicit w_nud_det(_In_ std::string& nudity_detection_model_path);\n\n  /*!\n          The deconstructor of the class.\n  */\n  ~w_nud_det();\n\n  /*!\n  The function gets a string as input and return the boolean representation of the input.\n\n          \\param pVariable the string input.\n          \\return a vector of float numbers each between 0 to 1 that shows the nudity factors.\n  */\n  W_API auto nudity_detection(_In_ uint8_t* pImageData, _In_ int pImageWidth, _In_ int pImageHeight,\n                              _In_ int pImageChannels) -> std::vector<float>;\n\n  /*!\n  The function uses to warm-up the network in the w_nud_det class initialization.\n\n          \\param pHeight the temp image height.\n          \\param pWidth the temp image width.\n          \\return (void)\n  */\n  W_API auto network_warm_up(_In_ int pHeight, _In_ int pWidth) -> void;\n\n private:\n  // :cppflow:model _model;\n  torch::jit::script::Module _model;\n};\n}  // namespace wolf::ml::nudet\n"
  },
  {
    "path": "wolf/ml/referee_ocr/salieri.h",
    "content": "/**\n * Salieri\n * v1\n *\n * Salieri is a header which contains definitions for the Microsoft\n * source-code annotation language (SAL).  It is *not* an\n * implementation of SAL; that's for compilers and static analyzers.\n * For the most part we just define macros to nothing.\n *\n * The goal is to allow projects to use SAL without creating a hard\n * dependency on it (i.e., you can still use compilers other than\n * MSVC).  Simply include `salieri.h`, which you can/should distribute\n * with your code, instead of `<sal.h>`.\n *\n * Multiple copies of Salieri can be included safely, even different\n * versions.  Including a newer version will simiply replace older\n * definitions with newer ones, and including older versions will have\n * no effect.\n *\n * I don't think anything in here is copyrightable, but just in case:\n *\n *   To the extent possible under law, the author(s) have dedicated\n *   all copyright and related and neighboring rights to this software\n *   to the public domain worldwide. This software is distributed\n *   without any warranty.\n *\n *   For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.\n */\n\n#if !defined(SALIERI_VERSION) || (SALIERI_VERSION < 1)\n\n/* TODO: figure out when <sal.h> first appeared. */\n#if defined(_MSC_VER)\n#include <sal.h>\n#elif defined(__has_include)\n#if __has_include(<sal.h>)\n#include <sal.h>\n#endif\n#endif\n\n/* The main concern for the implementation is that we don't want to\n * replace annotations from <sal.h>, but we *do* want to replace\n * annotations from older versions of Salieri.  To keep track of\n * everything, when we (Salieri) define a SAL annotation, we also\n * define SALIERI_DEFINED_${annotation} (with the leading and trailing\n * '-' stripped).  Then, before redefining an annotation macro we\n * check to make sure SALIERI_DEFINED_${annontation} is defined.\n *\n * This means you can safely use Salieri in a public header in your\n * project.\n */\n\n/* Function Parameters & Return Value\n *\n * https://msdn.microsoft.com/en-us/library/hh916382.aspx\n *****/\n\n/*  Pointer Parameters */\n\n#if defined(_In_) && defined(SALIERI_DEFINED_In)\n#undef _In_\n#endif\n#if !defined(_In_)\n#define _In_\n#define SALIERI_DEFINED_In\n#endif\n\n#if defined(_Out_) && defined(SALIERI_DEFINED_Out)\n#undef _Out_\n#endif\n#if !defined(_Out_)\n#define _Out_\n#define SALIERI_DEFINED_Out\n#endif\n\n#if defined(_Inout_) && defined(SALIERI_DEFINED_Inout)\n#undef _Inout_\n#endif\n#if !defined(_Inout_)\n#define _Inout_\n#define SALIERI_DEFINED_Inout\n#endif\n\n#if defined(_In_z_) && defined(SALIERI_DEFINED_In_z)\n#undef _In_z_\n#endif\n#if !defined(_In_z_)\n#define _In_z_\n#define SALIERI_DEFINED_In_z\n#endif\n\n#if defined(_Inout_z_) && defined(SALIERI_DEFINED_Inout_z)\n#undef _Inout_z_\n#endif\n#if !defined(_Inout_z_)\n#define _Inout_z_\n#define SALIERI_DEFINED_Inout_z\n#endif\n\n#if defined(_In_reads_) && defined(SALIERI_DEFINED_In_reads)\n#undef _In_reads_\n#endif\n#if !defined(_In_reads_)\n#define _In_reads_(s)\n#define SALIERI_DEFINED_In_reads\n#endif\n\n#if defined(_In_reads_bytes_) && defined(SALIERI_DEFINED_In_reads_bytes)\n#undef _In_reads_bytes_\n#endif\n#if !defined(_In_reads_bytes_)\n#define _In_reads_bytes_(s)\n#define SALIERI_DEFINED_In_reads_bytes\n#endif\n\n#if defined(_In_reads_z_) && defined(SALIERI_DEFINED_In_reads_z)\n#undef _In_reads_z_\n#endif\n#if !defined(_In_reads_z_)\n#define _In_reads_z_(s)\n#define SALIERI_DEFINED_In_reads_z\n#endif\n\n#if defined(_In_reads_or_z_) && defined(SALIERI_DEFINED_In_reads_or_z)\n#undef _In_reads_or_z_\n#endif\n#if !defined(_In_reads_or_z_)\n#define _In_reads_or_z_(s)\n#define SALIERI_DEFINED_In_reads_or_z\n#endif\n\n#if defined(_Out_writes_) && defined(SALIERI_DEFINED_Out_writes)\n#undef _Out_writes_\n#endif\n#if !defined(_Out_writes_)\n#define _Out_writes_(s)\n#define SALIERI_DEFINED_Out_writes\n#endif\n\n#if defined(_Out_writes_bytes_) && defined(SALIERI_DEFINED_Out_writes_bytes)\n#undef _Out_writes_bytes_\n#endif\n#if !defined(_Out_writes_bytes_)\n#define _Out_writes_bytes_(s)\n#define SALIERI_DEFINED_Out_writes_bytes\n#endif\n\n#if defined(_Out_writes_z_) && defined(SALIERI_DEFINED_Out_writes_z)\n#undef _Out_writes_z_\n#endif\n#if !defined(_Out_writes_z_)\n#define _Out_writes_z_(s)\n#define SALIERI_DEFINED_Out_writes_z\n#endif\n\n#if defined(_Inout_updates_) && defined(SALIERI_DEFINED_Inout_updates)\n#undef _Inout_updates_\n#endif\n#if !defined(_Inout_updates_)\n#define _Inout_updates_(s)\n#define SALIERI_DEFINED_Inout_updates\n#endif\n\n#if defined(_Inout_updates_bytes_) && defined(SALIERI_DEFINED_Inout_updates_bytes)\n#undef _Inout_updates_bytes_\n#endif\n#if !defined(_Inout_updates_bytes_)\n#define _Inout_updates_bytes_(s)\n#define SALIERI_DEFINED_Inout_updates_bytes\n#endif\n\n#if defined(_Inout_updates_z_) && defined(SALIERI_DEFINED_Inout_updates_z)\n#undef _Inout_updates_z_\n#endif\n#if !defined(_Inout_updates_z_)\n#define _Inout_updates_z_(s)\n#define SALIERI_DEFINED_Inout_updates_z\n#endif\n\n#if defined(_Out_writes_to_) && defined(SALIERI_DEFINED_Out_writes_to)\n#undef _Out_writes_to_\n#endif\n#if !defined(_Out_writes_to_)\n#define _Out_writes_to_(s, c)\n#define SALIERI_DEFINED_Out_writes_to\n#endif\n\n#if defined(_Out_writes_bytes_to_) && defined(SALIERI_DEFINED_Out_writes_bytes_to)\n#undef _Out_writes_bytes_to_\n#endif\n#if !defined(_Out_writes_bytes_to_)\n#define _Out_writes_bytes_to_(s, c)\n#define SALIERI_DEFINED_Out_writes_bytes_to\n#endif\n\n#if defined(_Out_writes_all_) && defined(SALIERI_DEFINED_Out_writes_all)\n#undef _Out_writes_all_\n#endif\n#if !defined(_Out_writes_all_)\n#define _Out_writes_all_(s)\n#define SALIERI_DEFINED_Out_writes_all\n#endif\n\n#if defined(_Out_writes_bytes_all_) && defined(SALIERI_DEFINED_Out_writes_bytes_all)\n#undef _Out_writes_bytes_all_\n#endif\n#if !defined(_Out_writes_bytes_all_)\n#define _Out_writes_bytes_all_(s)\n#define SALIERI_DEFINED_Out_writes_bytes_all\n#endif\n\n#if defined(_In_updates_to_) && defined(SALIERI_DEFINED_In_updates_to)\n#undef _In_updates_to_\n#endif\n#if !defined(_In_updates_to_)\n#define _In_updates_to_(s, c)\n#define SALIERI_DEFINED_In_updates_to\n#endif\n\n#if defined(_In_updates_bytes_to_) && defined(SALIERI_DEFINED_In_updates_bytes_to)\n#undef _In_updates_bytes_to_\n#endif\n#if !defined(_In_updates_bytes_to_)\n#define _In_updates_bytes_to_(s, c)\n#define SALIERI_DEFINED_In_updates_bytes_to\n#endif\n\n#if defined(_Inout_updates_z_) && defined(SALIERI_DEFINED_Inout_updates_z)\n#undef _Inout_updates_z_\n#endif\n#if !defined(_Inout_updates_z_)\n#define _Inout_updates_z_(s)\n#define SALIERI_DEFINED_Inout_updates_z\n#endif\n\n#if defined(_Out_writes_to_) && defined(SALIERI_DEFINED_Out_writes_to)\n#undef _Out_writes_to_\n#endif\n#if !defined(_Out_writes_to_)\n#define _Out_writes_to_(s, c)\n#define SALIERI_DEFINED_Out_writes_to\n#endif\n\n#if defined(_Out_writes_bytes_to_) && defined(SALIERI_DEFINED_Out_writes_bytes_to)\n#undef _Out_writes_bytes_to_\n#endif\n#if !defined(_Out_writes_bytes_to_)\n#define _Out_writes_bytes_to_(s, c)\n#define SALIERI_DEFINED_Out_writes_bytes_to\n#endif\n\n#if defined(_Out_writes_all_) && defined(SALIERI_DEFINED_Out_writes_all)\n#undef _Out_writes_all_\n#endif\n#if !defined(_Out_writes_all_)\n#define _Out_writes_all_(s)\n#define SALIERI_DEFINED_Out_writes_all\n#endif\n\n#if defined(_Out_writes_bytes_all_) && defined(SALIERI_DEFINED_Out_writes_bytes_all)\n#undef _Out_writes_bytes_all_\n#endif\n#if !defined(_Out_writes_bytes_all_)\n#define _Out_writes_bytes_all_(s)\n#define SALIERI_DEFINED_Out_writes_bytes_all\n#endif\n\n#if defined(_Inout_updates_to_) && defined(SALIERI_DEFINED_Inout_updates_to)\n#undef _Inout_updates_to_\n#endif\n#if !defined(_Inout_updates_to_)\n#define _Inout_updates_to_(s, c)\n#define SALIERI_DEFINED_Inout_updates_to\n#endif\n\n#if defined(_Inout_updates_bytes_to_) && defined(SALIERI_DEFINED_Inout_updates_bytes_to)\n#undef _Inout_updates_bytes_to_\n#endif\n#if !defined(_Inout_updates_bytes_to_)\n#define _Inout_updates_bytes_to_(s, c)\n#define SALIERI_DEFINED_Inout_updates_bytes_to\n#endif\n\n#if defined(_Inout_updates_all_) && defined(SALIERI_DEFINED_Inout_updates_all)\n#undef _Inout_updates_all_\n#endif\n#if !defined(_Inout_updates_all_)\n#define _Inout_updates_all_(s)\n#define SALIERI_DEFINED_Inout_updates_all\n#endif\n\n#if defined(_Inout_updates_bytes_all_) && defined(SALIERI_DEFINED_Inout_updates_bytes_all)\n#undef _Inout_updates_bytes_all_\n#endif\n#if !defined(_Inout_updates_bytes_all_)\n#define _Inout_updates_bytes_all_(s)\n#define SALIERI_DEFINED_Inout_updates_bytes_all\n#endif\n\n#if defined(_In_reads_to_ptr_) && defined(SALIERI_DEFINED_In_reads_to_ptr)\n#undef _In_reads_to_ptr_\n#endif\n#if !defined(_In_reads_to_ptr_)\n#define _In_reads_to_ptr_(p)\n#define SALIERI_DEFINED_In_reads_to_ptr\n#endif\n\n#if defined(_In_reads_to_ptr_z_) && defined(SALIERI_DEFINED_In_reads_to_ptr_z)\n#undef _In_reads_to_ptr_z_\n#endif\n#if !defined(_In_reads_to_ptr_z_)\n#define _In_reads_to_ptr_z_(p)\n#define SALIERI_DEFINED_In_reads_to_ptr_z\n#endif\n\n#if defined(_Out_writes_to_ptr_) && defined(SALIERI_DEFINED_Out_writes_to_ptr)\n#undef _Out_writes_to_ptr_\n#endif\n#if !defined(_Out_writes_to_ptr_)\n#define _Out_writes_to_ptr_(p)\n#define SALIERI_DEFINED_Out_writes_to_ptr\n#endif\n\n#if defined(_Out_writes_to_ptr_z_) && defined(SALIERI_DEFINED_Out_writes_to_ptr_z)\n#undef _Out_writes_to_ptr_z_\n#endif\n#if !defined(_Out_writes_to_ptr_z_)\n#define _Out_writes_to_ptr_z_(p)\n#define SALIERI_DEFINED_Out_writes_to_ptr_z\n#endif\n\n/*  Optional Pointer Parameters */\n\n#if defined(_In_opt_) && defined(SALIERI_DEFINED_In_opt)\n#undef _In_opt_\n#endif\n#if !defined(_In_opt_)\n#define _In_opt_\n#define SALIERI_DEFINED_In_opt\n#endif\n\n#if defined(_Out_opt_) && defined(SALIERI_DEFINED_Out_opt)\n#undef _Out_opt_\n#endif\n#if !defined(_Out_opt_)\n#define _Out_opt_\n#define SALIERI_DEFINED_Out_opt\n#endif\n\n#if defined(_Inout_opt_) && defined(SALIERI_DEFINED_Inout_opt)\n#undef _Inout_opt_\n#endif\n#if !defined(_Inout_opt_)\n#define _Inout_opt_\n#define SALIERI_DEFINED_Inout_opt\n#endif\n\n#if defined(_In_opt_z_) && defined(SALIERI_DEFINED_In_opt_z)\n#undef _In_opt_z_\n#endif\n#if !defined(_In_opt_z_)\n#define _In_opt_z_\n#define SALIERI_DEFINED_In_opt_z\n#endif\n\n#if defined(_Inout_opt_z_) && defined(SALIERI_DEFINED_Inout_opt_z)\n#undef _Inout_opt_z_\n#endif\n#if !defined(_Inout_opt_z_)\n#define _Inout_opt_z_\n#define SALIERI_DEFINED_Inout_opt_z\n#endif\n\n#if defined(_In_reads_opt_) && defined(SALIERI_DEFINED_In_reads_opt)\n#undef _In_reads_opt_\n#endif\n#if !defined(_In_reads_opt_)\n#define _In_reads_opt_(s)\n#define SALIERI_DEFINED_In_reads_opt\n#endif\n\n#if defined(_In_reads_bytes_opt_) && defined(SALIERI_DEFINED_In_reads_bytes_opt)\n#undef _In_reads_bytes_opt_\n#endif\n#if !defined(_In_reads_bytes_opt_)\n#define _In_reads_bytes_opt_(s)\n#define SALIERI_DEFINED_In_reads_bytes_opt\n#endif\n\n#if defined(_In_reads_opt_z_) && defined(SALIERI_DEFINED_In_reads_opt_z)\n#undef _In_reads_opt_z_\n#endif\n#if !defined(_In_reads_opt_z_)\n#define _In_reads_opt_z_(s)\n#define SALIERI_DEFINED_In_reads_opt_z\n#endif\n\n#if defined(_Out_writes_opt_) && defined(SALIERI_DEFINED_Out_writes_opt)\n#undef _Out_writes_opt_\n#endif\n#if !defined(_Out_writes_opt_)\n#define _Out_writes_opt_(s)\n#define SALIERI_DEFINED_Out_writes_opt\n#endif\n\n#if defined(_Out_writes_bytes_) && defined(SALIERI_DEFINED_Out_writes_bytes)\n#undef _Out_writes_bytes_\n#endif\n#if !defined(_Out_writes_bytes_)\n#define _Out_writes_bytes_(s)\n#define SALIERI_DEFINED_Out_writes_bytes\n#endif\n\n#if defined(_Out_writes_opt_z_) && defined(SALIERI_DEFINED_Out_writes_opt_z)\n#undef _Out_writes_opt_z_\n#endif\n#if !defined(_Out_writes_opt_z_)\n#define _Out_writes_opt_z_(s)\n#define SALIERI_DEFINED_Out_writes_opt_z\n#endif\n\n#if defined(_Inout_updates_opt_) && defined(SALIERI_DEFINED_Inout_updates_opt)\n#undef _Inout_updates_opt_\n#endif\n#if !defined(_Inout_updates_opt_)\n#define _Inout_updates_opt_(s)\n#define SALIERI_DEFINED_Inout_updates_opt\n#endif\n\n#if defined(_Inout_updates_bytes_opt_) && defined(SALIERI_DEFINED_Inout_updates_bytes_opt)\n#undef _Inout_updates_bytes_opt_\n#endif\n#if !defined(_Inout_updates_bytes_opt_)\n#define _Inout_updates_bytes_opt_(s)\n#define SALIERI_DEFINED_Inout_updates_bytes_opt\n#endif\n\n#if defined(_Inout_updates_opt_z_) && defined(SALIERI_DEFINED_Inout_updates_opt_z)\n#undef _Inout_updates_opt_z_\n#endif\n#if !defined(_Inout_updates_opt_z_)\n#define _Inout_updates_opt_z_(s)\n#define SALIERI_DEFINED_Inout_updates_opt_z\n#endif\n\n#if defined(_Out_writes_to_opt_) && defined(SALIERI_DEFINED_Out_writes_to_opt)\n#undef _Out_writes_to_opt_\n#endif\n#if !defined(_Out_writes_to_opt_)\n#define _Out_writes_to_opt_(s, c)\n#define SALIERI_DEFINED_Out_writes_to_opt\n#endif\n\n#if defined(_Out_writes_bytes_to_opt_) && defined(SALIERI_DEFINED_Out_writes_bytes_to_opt)\n#undef _Out_writes_bytes_to_opt_\n#endif\n#if !defined(_Out_writes_bytes_to_opt_)\n#define _Out_writes_bytes_to_opt_(s, c)\n#define SALIERI_DEFINED_Out_writes_bytes_to_opt\n#endif\n\n#if defined(_Out_writes_all_opt_) && defined(SALIERI_DEFINED_Out_writes_all_opt)\n#undef _Out_writes_all_opt_\n#endif\n#if !defined(_Out_writes_all_opt_)\n#define _Out_writes_all_opt_(s)\n#define SALIERI_DEFINED_Out_writes_all_opt\n#endif\n\n#if defined(_Out_writes_bytes_all_opt_) && defined(SALIERI_DEFINED_Out_writes_bytes_all_opt)\n#undef _Out_writes_bytes_all_opt_\n#endif\n#if !defined(_Out_writes_bytes_all_opt_)\n#define _Out_writes_bytes_all_opt_(s)\n#define SALIERI_DEFINED_Out_writes_bytes_all_opt\n#endif\n\n#if defined(_In_updates_to_opt_) && defined(SALIERI_DEFINED_In_updates_to_opt)\n#undef _In_updates_to_opt_\n#endif\n#if !defined(_In_updates_to_opt_)\n#define _In_updates_to_opt_(s, c)\n#define SALIERI_DEFINED_In_updates_to_opt\n#endif\n\n#if defined(_In_updates_bytes_to_opt_) && defined(SALIERI_DEFINED_In_updates_bytes_to_opt)\n#undef _In_updates_bytes_to_opt_\n#endif\n#if !defined(_In_updates_bytes_to_opt_)\n#define _In_updates_bytes_to_opt_(s, c)\n#define SALIERI_DEFINED_In_updates_bytes_to_opt\n#endif\n\n#if defined(_Inout_updates_all_opt_) && defined(SALIERI_DEFINED_Inout_updates_all_opt)\n#undef _Inout_updates_all_opt_\n#endif\n#if !defined(_Inout_updates_all_opt_)\n#define _Inout_updates_all_opt_(s)\n#define SALIERI_DEFINED_Inout_updates_all_opt\n#endif\n\n#if defined(_Inout_updates_bytes_all_opt_) && defined(SALIERI_DEFINED_Inout_updates_bytes_all_opt)\n#undef _Inout_updates_bytes_all_opt_\n#endif\n#if !defined(_Inout_updates_bytes_all_opt_)\n#define _Inout_updates_bytes_all_opt_(s)\n#define SALIERI_DEFINED_Inout_updates_bytes_all_opt\n#endif\n\n#if defined(_In_reads_to_ptr_opt_) && defined(SALIERI_DEFINED_In_reads_to_ptr_opt)\n#undef _In_reads_to_ptr_opt_\n#endif\n#if !defined(_In_reads_to_ptr_opt_)\n#define _In_reads_to_ptr_opt_(p)\n#define SALIERI_DEFINED_In_reads_to_ptr_opt\n#endif\n\n#if defined(_In_reads_to_ptr_opt_z_) && defined(SALIERI_DEFINED_In_reads_to_ptr_opt_z)\n#undef _In_reads_to_ptr_opt_z_\n#endif\n#if !defined(_In_reads_to_ptr_opt_z_)\n#define _In_reads_to_ptr_opt_z_(p)\n#define SALIERI_DEFINED_In_reads_to_ptr_opt_z\n#endif\n\n#if defined(_Out_writes_to_ptr_opt_) && defined(SALIERI_DEFINED_Out_writes_to_ptr_opt)\n#undef _Out_writes_to_ptr_opt_\n#endif\n#if !defined(_Out_writes_to_ptr_opt_)\n#define _Out_writes_to_ptr_opt_(p)\n#define SALIERI_DEFINED_Out_writes_to_ptr_opt\n#endif\n\n#if defined(_Out_writes_to_ptr_opt_z_) && defined(SALIERI_DEFINED_Out_writes_to_ptr_opt_z)\n#undef _Out_writes_to_ptr_opt_z_\n#endif\n#if !defined(_Out_writes_to_ptr_opt_z_)\n#define _Out_writes_to_ptr_opt_z_(p)\n#define SALIERI_DEFINED_Out_writes_to_ptr_opt_z\n#endif\n\n/* Output Pointer Parameters */\n\n#if defined(_Outptr_) && defined(SALIERI_DEFINED_Outptr)\n#undef _Outptr_\n#endif\n#if !defined(_Outptr_)\n#define _Outptr_\n#define SALIERI_DEFINED_Outptr\n#endif\n\n#if defined(_Outptr_opt_) && defined(SALIERI_DEFINED_Outptr_opt)\n#undef _Outptr_opt_\n#endif\n#if !defined(_Outptr_opt_)\n#define _Outptr_opt_\n#define SALIERI_DEFINED_Outptr_opt\n#endif\n\n#if defined(_Outptr_result_maybenull_) && defined(SALIERI_DEFINED_Outptr_result_maybenull)\n#undef _Outptr_result_maybenull_\n#endif\n#if !defined(_Outptr_result_maybenull_)\n#define _Outptr_result_maybenull_\n#define SALIERI_DEFINED_Outptr_result_maybenull\n#endif\n\n#if defined(_Outptr_opt_result_maybenull_) && defined(SALIERI_DEFINED_Outptr_opt_result_maybenull)\n#undef _Outptr_opt_result_maybenull_\n#endif\n#if !defined(_Outptr_opt_result_maybenull_)\n#define _Outptr_opt_result_maybenull_\n#define SALIERI_DEFINED_Outptr_opt_result_maybenull\n#endif\n\n#if defined(_Outptr_result_z_) && defined(SALIERI_DEFINED_Outptr_result_z)\n#undef _Outptr_result_z_\n#endif\n#if !defined(_Outptr_result_z_)\n#define _Outptr_result_z_\n#define SALIERI_DEFINED_Outptr_result_z\n#endif\n\n#if defined(_Outptr_opt_result_z_) && defined(SALIERI_DEFINED_Outptr_opt_result_z)\n#undef _Outptr_opt_result_z_\n#endif\n#if !defined(_Outptr_opt_result_z_)\n#define _Outptr_opt_result_z_\n#define SALIERI_DEFINED_Outptr_opt_result_z\n#endif\n\n#if defined(_Outptr_result_maybenull_z_) && defined(SALIERI_DEFINED_Outptr_result_maybenull_z)\n#undef _Outptr_result_maybenull_z_\n#endif\n#if !defined(_Outptr_result_maybenull_z_)\n#define _Outptr_result_maybenull_z_\n#define SALIERI_DEFINED_Outptr_result_maybenull_z\n#endif\n\n#if defined(_Outptr_opt_result_maybenull_z_) && defined(SALIERI_DEFINED_Outptr_opt_result_maybenull_z)\n#undef _Outptr_opt_result_maybenull_z_\n#endif\n#if !defined(_Outptr_opt_result_maybenull_z_)\n#define _Outptr_opt_result_maybenull_z_\n#define SALIERI_DEFINED_Outptr_opt_result_maybenull_z\n#endif\n\n#if defined(_COM_Outptr_) && defined(SALIERI_DEFINED_COM_Outptr)\n#undef _COM_Outptr_\n#endif\n#if !defined(_COM_Outptr_)\n#define _COM_Outptr_\n#define SALIERI_DEFINED_COM_Outptr\n#endif\n\n#if defined(_COM_Outptr_opt_) && defined(SALIERI_DEFINED_COM_Outptr_opt)\n#undef _COM_Outptr_opt_\n#endif\n#if !defined(_COM_Outptr_opt_)\n#define _COM_Outptr_opt_\n#define SALIERI_DEFINED_COM_Outptr_opt\n#endif\n\n#if defined(_COM_Outptr_result_maybenull_) && defined(SALIERI_DEFINED_COM_Outptr_result_maybenull)\n#undef _COM_Outptr_result_maybenull_\n#endif\n#if !defined(_COM_Outptr_result_maybenull_)\n#define _COM_Outptr_result_maybenull_\n#define SALIERI_DEFINED_COM_Outptr_result_maybenull\n#endif\n\n#if defined(_Outptr_opt_result_maybenull_) && defined(SALIERI_DEFINED_Outptr_opt_result_maybenull)\n#undef _Outptr_opt_result_maybenull_\n#endif\n#if !defined(_Outptr_opt_result_maybenull_)\n#define _Outptr_opt_result_maybenull_\n#define SALIERI_DEFINED_Outptr_opt_result_maybenull\n#endif\n\n#if defined(_Outptr_result_buffer_) && defined(SALIERI_DEFINED_Outptr_result_buffer)\n#undef _Outptr_result_buffer_\n#endif\n#if !defined(_Outptr_result_buffer_)\n#define _Outptr_result_buffer_(s)\n#define SALIERI_DEFINED_Outptr_result_buffer\n#endif\n\n#if defined(_Outptr_result_bytebuffer_) && defined(SALIERI_DEFINED_Outptr_result_bytebuffer)\n#undef _Outptr_result_bytebuffer_\n#endif\n#if !defined(_Outptr_result_bytebuffer_)\n#define _Outptr_result_bytebuffer_(s)\n#define SALIERI_DEFINED_Outptr_result_bytebuffer\n#endif\n\n#if defined(_Outptr_opt_result_buffer_) && defined(SALIERI_DEFINED_Outptr_opt_result_buffer)\n#undef _Outptr_opt_result_buffer_\n#endif\n#if !defined(_Outptr_opt_result_buffer_)\n#define _Outptr_opt_result_buffer_(s)\n#define SALIERI_DEFINED_Outptr_opt_result_buffer\n#endif\n\n#if defined(_Outptr_opt_result_bytebuffer_) && defined(SALIERI_DEFINED_Outptr_opt_result_bytebuffer)\n#undef _Outptr_opt_result_bytebuffer_\n#endif\n#if !defined(_Outptr_opt_result_bytebuffer_)\n#define _Outptr_opt_result_bytebuffer_(s)\n#define SALIERI_DEFINED_Outptr_opt_result_bytebuffer\n#endif\n\n#if defined(_Outptr_result_buffer_to_) && defined(SALIERI_DEFINED_Outptr_result_buffer_to)\n#undef _Outptr_result_buffer_to_\n#endif\n#if !defined(_Outptr_result_buffer_to_)\n#define _Outptr_result_buffer_to_(s, c)\n#define SALIERI_DEFINED_Outptr_result_buffer_to\n#endif\n\n#if defined(_Outptr_result_bytebuffer_to_) && defined(SALIERI_DEFINED_Outptr_result_bytebuffer_to)\n#undef _Outptr_result_bytebuffer_to_\n#endif\n#if !defined(_Outptr_result_bytebuffer_to_)\n#define _Outptr_result_bytebuffer_to_(s, c)\n#define SALIERI_DEFINED_Outptr_result_bytebuffer_to\n#endif\n\n#if defined(_Outptr_opt_result_buffer_to_) && defined(SALIERI_DEFINED_Outptr_opt_result_buffer_to)\n#undef _Outptr_opt_result_buffer_to_\n#endif\n#if !defined(_Outptr_opt_result_buffer_to_)\n#define _Outptr_opt_result_buffer_to_(s, c)\n#define SALIERI_DEFINED_Outptr_opt_result_buffer_to\n#endif\n\n#if defined(_Outptr_opt_result_bytebuffer_to_) && defined(SALIERI_DEFINED_Outptr_opt_result_bytebuffer_to)\n#undef _Outptr_opt_result_bytebuffer_to_\n#endif\n#if !defined(_Outptr_opt_result_bytebuffer_to_)\n#define _Outptr_opt_result_bytebuffer_to_(s, c)\n#define SALIERI_DEFINED_Outptr_opt_result_bytebuffer_to\n#endif\n\n#if defined(_Result_nullonfailure_) && defined(SALIERI_DEFINED_Result_nullonfailure)\n#undef _Result_nullonfailure_\n#endif\n#if !defined(_Result_nullonfailure_)\n#define _Result_nullonfailure_\n#define SALIERI_DEFINED_Result_nullonfailure\n#endif\n\n#if defined(_Result_zeroonfailure_) && defined(SALIERI_DEFINED_Result_zeroonfailure)\n#undef _Result_zeroonfailure_\n#endif\n#if !defined(_Result_zeroonfailure_)\n#define _Result_zeroonfailure_\n#define SALIERI_DEFINED_Result_zeroonfailure\n#endif\n\n#if defined(_Outptr_result_nullonfailure_) && defined(SALIERI_DEFINED_Outptr_result_nullonfailure)\n#undef _Outptr_result_nullonfailure_\n#endif\n#if !defined(_Outptr_result_nullonfailure_)\n#define _Outptr_result_nullonfailure_\n#define SALIERI_DEFINED_Outptr_result_nullonfailure\n#endif\n\n#if defined(_Outptr_opt_result_nullonfailure_) && defined(SALIERI_DEFINED_Outptr_opt_result_nullonfailure)\n#undef _Outptr_opt_result_nullonfailure_\n#endif\n#if !defined(_Outptr_opt_result_nullonfailure_)\n#define _Outptr_opt_result_nullonfailure_\n#define SALIERI_DEFINED_Outptr_opt_result_nullonfailure\n#endif\n\n#if defined(_Outref_result_nullonfailure_) && defined(SALIERI_DEFINED_Outref_result_nullonfailure)\n#undef _Outref_result_nullonfailure_\n#endif\n#if !defined(_Outref_result_nullonfailure_)\n#define _Outref_result_nullonfailure_\n#define SALIERI_DEFINED_Outref_result_nullonfailure\n#endif\n\n/* Output Reference Parameters */\n\n#if defined(_Outref_) && defined(SALIERI_DEFINED_Outref)\n#undef _Outref_\n#endif\n#if !defined(_Outref_)\n#define _Outref_\n#define SALIERI_DEFINED_Outref\n#endif\n\n#if defined(_Outref_result_maybenull_) && defined(SALIERI_DEFINED_Outref_result_maybenull)\n#undef _Outref_result_maybenull_\n#endif\n#if !defined(_Outref_result_maybenull_)\n#define _Outref_result_maybenull_\n#define SALIERI_DEFINED_Outref_result_maybenull\n#endif\n\n#if defined(_Outref_result_buffer_) && defined(SALIERI_DEFINED_Outref_result_buffer)\n#undef _Outref_result_buffer_\n#endif\n#if !defined(_Outref_result_buffer_)\n#define _Outref_result_buffer_(s)\n#define SALIERI_DEFINED_Outref_result_buffer\n#endif\n\n#if defined(_Outref_result_bytebuffer_) && defined(SALIERI_DEFINED_Outref_result_bytebuffer)\n#undef _Outref_result_bytebuffer_\n#endif\n#if !defined(_Outref_result_bytebuffer_)\n#define _Outref_result_bytebuffer_(s)\n#define SALIERI_DEFINED_Outref_result_bytebuffer\n#endif\n\n#if defined(_Outref_result_buffer_to_) && defined(SALIERI_DEFINED_Outref_result_buffer_to)\n#undef _Outref_result_buffer_to_\n#endif\n#if !defined(_Outref_result_buffer_to_)\n#define _Outref_result_buffer_to_(s, c)\n#define SALIERI_DEFINED_Outref_result_buffer_to\n#endif\n\n#if defined(_Outref_result_bytebuffer_to_) && defined(SALIERI_DEFINED_Outref_result_bytebuffer_to)\n#undef _Outref_result_bytebuffer_to_\n#endif\n#if !defined(_Outref_result_bytebuffer_to_)\n#define _Outref_result_bytebuffer_to_(s, c)\n#define SALIERI_DEFINED_Outref_result_bytebuffer_to\n#endif\n\n#if defined(_Outref_result_buffer_all_) && defined(SALIERI_DEFINED_Outref_result_buffer_all)\n#undef _Outref_result_buffer_all_\n#endif\n#if !defined(_Outref_result_buffer_all_)\n#define _Outref_result_buffer_all_(s)\n#define SALIERI_DEFINED_Outref_result_buffer_all\n#endif\n\n#if defined(_Outref_result_bytebuffer_all_) && defined(SALIERI_DEFINED_Outref_result_bytebuffer_all)\n#undef _Outref_result_bytebuffer_all_\n#endif\n#if !defined(_Outref_result_bytebuffer_all_)\n#define _Outref_result_bytebuffer_all_(s)\n#define SALIERI_DEFINED_Outref_result_bytebuffer_all\n#endif\n\n#if defined(_Outref_result_buffer_maybenull_) && defined(SALIERI_DEFINED_Outref_result_buffer_maybenull)\n#undef _Outref_result_buffer_maybenull_\n#endif\n#if !defined(_Outref_result_buffer_maybenull_)\n#define _Outref_result_buffer_maybenull_(s)\n#define SALIERI_DEFINED_Outref_result_buffer_maybenull\n#endif\n\n#if defined(_Outref_result_bytebuffer_maybenull_) && defined(SALIERI_DEFINED_Outref_result_bytebuffer_maybenull)\n#undef _Outref_result_bytebuffer_maybenull_\n#endif\n#if !defined(_Outref_result_bytebuffer_maybenull_)\n#define _Outref_result_bytebuffer_maybenull_(s)\n#define SALIERI_DEFINED_Outref_result_bytebuffer_maybenull\n#endif\n\n#if defined(_Outref_result_buffer_to_maybenull_) && defined(SALIERI_DEFINED_Outref_result_buffer_to_maybenull)\n#undef _Outref_result_buffer_to_maybenull_\n#endif\n#if !defined(_Outref_result_buffer_to_maybenull_)\n#define _Outref_result_buffer_to_maybenull_(s, c)\n#define SALIERI_DEFINED_Outref_result_buffer_to_maybenull\n#endif\n\n#if defined(_Outref_result_bytebuffer_to_maybenull_) && defined(SALIERI_DEFINED_Outref_result_bytebuffer_to_maybenull)\n#undef _Outref_result_bytebuffer_to_maybenull_\n#endif\n#if !defined(_Outref_result_bytebuffer_to_maybenull_)\n#define _Outref_result_bytebuffer_to_maybenull_(s, c)\n#define SALIERI_DEFINED_Outref_result_bytebuffer_to_maybenull\n#endif\n\n#if defined(_Outref_result_buffer_all_maybenull_) && defined(SALIERI_DEFINED_Outref_result_buffer_all_maybenull)\n#undef _Outref_result_buffer_all_maybenull_\n#endif\n#if !defined(_Outref_result_buffer_all_maybenull_)\n#define _Outref_result_buffer_all_maybenull_(s)\n#define SALIERI_DEFINED_Outref_result_buffer_all_maybenull\n#endif\n\n#if defined(_Outref_result_bytebuffer_all_maybenull_) && defined(SALIERI_DEFINED_Outref_result_bytebuffer_all_maybenull)\n#undef _Outref_result_bytebuffer_all_maybenull_\n#endif\n#if !defined(_Outref_result_bytebuffer_all_maybenull_)\n#define _Outref_result_bytebuffer_all_maybenull_(s)\n#define SALIERI_DEFINED_Outref_result_bytebuffer_all_maybenull\n#endif\n\n/* Return Values */\n\n#if defined(_Ret_z_) && defined(SALIERI_DEFINED_Ret_z)\n#undef _Ret_z_\n#endif\n#if !defined(_Ret_z_)\n#define _Ret_z_\n#define SALIERI_DEFINED_Ret_z\n#endif\n\n#if defined(_Ret_writes_) && defined(SALIERI_DEFINED_Ret_writes)\n#undef _Ret_writes_\n#endif\n#if !defined(_Ret_writes_)\n#define _Ret_writes_(s)\n#define SALIERI_DEFINED_Ret_writes\n#endif\n\n#if defined(_Ret_writes_bytes_) && defined(SALIERI_DEFINED_Ret_writes_bytes)\n#undef _Ret_writes_bytes_\n#endif\n#if !defined(_Ret_writes_bytes_)\n#define _Ret_writes_bytes_(s)\n#define SALIERI_DEFINED_Ret_writes_bytes\n#endif\n\n#if defined(_Ret_writes_z_) && defined(SALIERI_DEFINED_Ret_writes_z)\n#undef _Ret_writes_z_\n#endif\n#if !defined(_Ret_writes_z_)\n#define _Ret_writes_z_(s)\n#define SALIERI_DEFINED_Ret_writes_z\n#endif\n\n#if defined(_Ret_writes_to_) && defined(SALIERI_DEFINED_Ret_writes_to)\n#undef _Ret_writes_to_\n#endif\n#if !defined(_Ret_writes_to_)\n#define _Ret_writes_to_(s, c)\n#define SALIERI_DEFINED_Ret_writes_to\n#endif\n\n#if defined(_Ret_writes_maybenull_) && defined(SALIERI_DEFINED_Ret_writes_maybenull)\n#undef _Ret_writes_maybenull_\n#endif\n#if !defined(_Ret_writes_maybenull_)\n#define _Ret_writes_maybenull_(s)\n#define SALIERI_DEFINED_Ret_writes_maybenull\n#endif\n\n#if defined(_Ret_writes_to_maybenull_) && defined(SALIERI_DEFINED_Ret_writes_to_maybenull)\n#undef _Ret_writes_to_maybenull_\n#endif\n#if !defined(_Ret_writes_to_maybenull_)\n#define _Ret_writes_to_maybenull_(s)\n#define SALIERI_DEFINED_Ret_writes_to_maybenull\n#endif\n\n#if defined(_Ret_writes_maybenull_z_) && defined(SALIERI_DEFINED_Ret_writes_maybenull_z)\n#undef _Ret_writes_maybenull_z_\n#endif\n#if !defined(_Ret_writes_maybenull_z_)\n#define _Ret_writes_maybenull_z_(s)\n#define SALIERI_DEFINED_Ret_writes_maybenull_z\n#endif\n\n#if defined(_Ret_maybenull_) && defined(SALIERI_DEFINED_Ret_maybenull)\n#undef _Ret_maybenull_\n#endif\n#if !defined(_Ret_maybenull_)\n#define _Ret_maybenull_\n#define SALIERI_DEFINED_Ret_maybenull\n#endif\n\n#if defined(_Ret_maybenull_z_) && defined(SALIERI_DEFINED_Ret_maybenull_z)\n#undef _Ret_maybenull_z_\n#endif\n#if !defined(_Ret_maybenull_z_)\n#define _Ret_maybenull_z_\n#define SALIERI_DEFINED_Ret_maybenull_z\n#endif\n\n#if defined(_Ret_null_) && defined(SALIERI_DEFINED_Ret_null)\n#undef _Ret_null_\n#endif\n#if !defined(_Ret_null_)\n#define _Ret_null_\n#define SALIERI_DEFINED_Ret_null\n#endif\n\n#if defined(_Ret_notnull_) && defined(SALIERI_DEFINED_Ret_notnull)\n#undef _Ret_notnull_\n#endif\n#if !defined(_Ret_notnull_)\n#define _Ret_notnull_\n#define SALIERI_DEFINED_Ret_notnull\n#endif\n\n#if defined(_Ret_writes_bytes_to_) && defined(SALIERI_DEFINED_Ret_writes_bytes_to)\n#undef _Ret_writes_bytes_to_\n#endif\n#if !defined(_Ret_writes_bytes_to_)\n#define _Ret_writes_bytes_to_\n#define SALIERI_DEFINED_Ret_writes_bytes_to\n#endif\n\n#if defined(_Ret_writes_bytes_to_) && defined(SALIERI_DEFINED_Ret_writes_bytes_to)\n#undef _Ret_writes_bytes_to_\n#endif\n#if !defined(_Ret_writes_bytes_to_)\n#define _Ret_writes_bytes_to_\n#define SALIERI_DEFINED_Ret_writes_bytes_to\n#endif\n\n#if defined(_Ret_writes_bytes_maybenull_) && defined(SALIERI_DEFINED_Ret_writes_bytes_maybenull)\n#undef _Ret_writes_bytes_maybenull_\n#endif\n#if !defined(_Ret_writes_bytes_maybenull_)\n#define _Ret_writes_bytes_maybenull_\n#define SALIERI_DEFINED_Ret_writes_bytes_maybenull\n#endif\n\n#if defined(_Ret_writes_bytes_to_maybenull_) && defined(SALIERI_DEFINED_Ret_writes_bytes_to_maybenull)\n#undef _Ret_writes_bytes_to_maybenull_\n#endif\n#if !defined(_Ret_writes_bytes_to_maybenull_)\n#define _Ret_writes_bytes_to_maybenull_\n#define SALIERI_DEFINED_Ret_writes_bytes_to_maybenull\n#endif\n\n/* Other Common Annotations */\n\n#if defined(_In_range_) && defined(SALIERI_DEFINED_In_range)\n#undef _In_range_\n#endif\n#if !defined(_In_range_)\n#define _In_range_(low, hi)\n#define SALIERI_DEFINED_In_range\n#endif\n\n#if defined(_Out_range_) && defined(SALIERI_DEFINED_Out_range)\n#undef _Out_range_\n#endif\n#if !defined(_Out_range_)\n#define _Out_range_(low, hi)\n#define SALIERI_DEFINED_Out_range\n#endif\n\n#if defined(_Ret_range_) && defined(SALIERI_DEFINED_Ret_range)\n#undef _Ret_range_\n#endif\n#if !defined(_Ret_range_)\n#define _Ret_range_(low, hi)\n#define SALIERI_DEFINED_Ret_range\n#endif\n\n#if defined(_Deref_in_range_) && defined(SALIERI_DEFINED_Deref_in_range)\n#undef _Deref_in_range_\n#endif\n#if !defined(_Deref_in_range_)\n#define _Deref_in_range_(low, hi)\n#define SALIERI_DEFINED_Deref_in_range\n#endif\n\n#if defined(_Deref_out_range_) && defined(SALIERI_DEFINED_Deref_out_range)\n#undef _Deref_out_range_\n#endif\n#if !defined(_Deref_out_range_)\n#define _Deref_out_range_(low, hi)\n#define SALIERI_DEFINED_Deref_out_range\n#endif\n\n#if defined(_Deref_inout_range_) && defined(SALIERI_DEFINED_Deref_inout_range)\n#undef _Deref_inout_range_\n#endif\n#if !defined(_Deref_inout_range_)\n#define _Deref_inout_range_(low, hi)\n#define SALIERI_DEFINED_Deref_inout_range\n#endif\n\n#if defined(_Field_range_) && defined(SALIERI_DEFINED_Field_range)\n#undef _Field_range_\n#endif\n#if !defined(_Field_range_)\n#define _Field_range_(low, hi)\n#define SALIERI_DEFINED_Field_range\n#endif\n\n#if defined(_Pre_equal_to_) && defined(SALIERI_DEFINED_Pre_equal_to)\n#undef _Pre_equal_to_\n#endif\n#if !defined(_Pre_equal_to_)\n#define _Pre_equal_to_(expr)\n#define SALIERI_DEFINED_Pre_equal_to\n#endif\n\n#if defined(_Post_equal_to_) && defined(SALIERI_DEFINED_Post_equal_to)\n#undef _Post_equal_to_\n#endif\n#if !defined(_Post_equal_to_)\n#define _Post_equal_to_(expr)\n#define SALIERI_DEFINED_Post_equal_to\n#endif\n\n#if defined(_Struct_size_bytes_) && defined(SALIERI_DEFINED_Struct_size_bytes)\n#undef _Struct_size_bytes_\n#endif\n#if !defined(_Struct_size_bytes_)\n#define _Struct_size_bytes_(size)\n#define SALIERI_DEFINED_Struct_size_bytes\n#endif\n\n/* Annotating Function Behavior\n *\n * https://msdn.microsoft.com/en-us/library/jj159529.aspx\n *****/\n\n#if defined(_Called_from_function_class_) && defined(SALIERI_DEFINED_Called_from_function_class)\n#undef _Called_from_function_class_\n#endif\n#if !defined(_Called_from_function_class_)\n#define _Called_from_function_class_(name)\n#define SALIERI_DEFINED_Called_from_function_class\n#endif\n\n#if defined(_Check_return_) && defined(SALIERI_DEFINED_Check_return)\n#undef _Check_return_\n#endif\n#if !defined(_Check_return_)\n#define _Check_return_\n#define SALIERI_DEFINED_Check_return\n#endif\n\n#if defined(_Function_class_) && defined(SALIERI_DEFINED_Function_class)\n#undef _Function_class_\n#endif\n#if !defined(_Function_class_)\n#define _Function_class_(name)\n#define SALIERI_DEFINED_Function_class\n#endif\n\n#if defined(_Raises_SEH_exception_) && defined(SALIERI_DEFINED_Raises_SEH_exception)\n#undef _Raises_SEH_exception_\n#endif\n#if !defined(_Raises_SEH_exception_)\n#define _Raises_SEH_exception_\n#define SALIERI_DEFINED_Raises_SEH_exception\n#endif\n\n#if defined(_Must_inspect_result_) && defined(SALIERI_DEFINED_Must_inspect_result)\n#undef _Must_inspect_result_\n#endif\n#if !defined(_Must_inspect_result_)\n#define _Must_inspect_result_\n#define SALIERI_DEFINED_Must_inspect_result\n#endif\n\n#if defined(_Use_decl_annotations_) && defined(SALIERI_DEFINED_Use_decl_annotations)\n#undef _Use_decl_annotations_\n#endif\n#if !defined(_Use_decl_annotations_)\n#define _Use_decl_annotations_\n#define SALIERI_DEFINED_Use_decl_annotations\n#endif\n\n#if defined(_Always_) && defined(SALIERI_DEFINED_Always)\n#undef _Always_\n#endif\n#if !defined(_Always_)\n#define _Always_(anno_list)\n#define SALIERI_DEFINED_Always\n#endif\n\n#if defined(_On_failure_) && defined(SALIERI_DEFINED_On_failure)\n#undef _On_failure_\n#endif\n#if !defined(_On_failure_)\n#define _On_failure_(anno_list)\n#define SALIERI_DEFINED_On_failure\n#endif\n\n#if defined(_Return_type_success_) && defined(SALIERI_DEFINED_Return_type_success)\n#undef _Return_type_success_\n#endif\n#if !defined(_Return_type_success_)\n#define _Return_type_success_(expr)\n#define SALIERI_DEFINED_Return_type_success\n#endif\n\n#if defined(_Success_) && defined(SALIERI_DEFINED_Success)\n#undef _Success_\n#endif\n#if !defined(_Success_)\n#define _Success_(expr)\n#define SALIERI_DEFINED_Success\n#endif\n\n/* Annotating Structs and Classes\n *\n * https://msdn.microsoft.com/en-us/library/jj159528.aspx\n *****/\n\n#if defined(_Field_range_) && defined(SALIERI_DEFINED_Field_range)\n#undef _Field_range_\n#endif\n#if !defined(_Field_range_)\n#define _Field_range_(low, high)\n#define SALIERI_DEFINED_Field_range\n#endif\n\n#if defined(_Field_size_) && defined(SALIERI_DEFINED_Field_size)\n#undef _Field_size_\n#endif\n#if !defined(_Field_size_)\n#define _Field_size_(size)\n#define SALIERI_DEFINED_Field_size\n#endif\n\n#if defined(_Field_size_part_) && defined(SALIERI_DEFINED_Field_size_part)\n#undef _Field_size_part_\n#endif\n#if !defined(_Field_size_part_)\n#define _Field_size_part_(size)\n#define SALIERI_DEFINED_Field_size_part\n#endif\n\n#if defined(_Field_size_opt_) && defined(SALIERI_DEFINED_Field_size_opt)\n#undef _Field_size_opt_\n#endif\n#if !defined(_Field_size_opt_)\n#define _Field_size_opt_(size)\n#define SALIERI_DEFINED_Field_size_opt\n#endif\n\n#if defined(_Field_size_bytes_) && defined(SALIERI_DEFINED_Field_size_bytes)\n#undef _Field_size_bytes_\n#endif\n#if !defined(_Field_size_bytes_)\n#define _Field_size_bytes_(size)\n#define SALIERI_DEFINED_Field_size_bytes\n#endif\n\n#if defined(_Field_size_bytes_opt_) && defined(SALIERI_DEFINED_Field_size_bytes_opt)\n#undef _Field_size_bytes_opt_\n#endif\n#if !defined(_Field_size_bytes_opt_)\n#define _Field_size_bytes_opt_(size)\n#define SALIERI_DEFINED_Field_size_bytes_opt\n#endif\n\n#if defined(_Field_size_part_) && defined(SALIERI_DEFINED_Field_size_part)\n#undef _Field_size_part_\n#endif\n#if !defined(_Field_size_part_)\n#define _Field_size_part_(size, count)\n#define SALIERI_DEFINED_Field_size_part\n#endif\n\n#if defined(_Field_size_part_opt_) && defined(SALIERI_DEFINED_Field_size_part_opt)\n#undef _Field_size_part_opt_\n#endif\n#if !defined(_Field_size_part_opt_)\n#define _Field_size_part_opt_(size, count)\n#define SALIERI_DEFINED_Field_size_part_opt\n#endif\n\n#if defined(_Field_size_bytes_part_) && defined(SALIERI_DEFINED_Field_size_bytes_part)\n#undef _Field_size_bytes_part_\n#endif\n#if !defined(_Field_size_bytes_part_)\n#define _Field_size_bytes_part_(size, count)\n#define SALIERI_DEFINED_Field_size_bytes_part\n#endif\n\n#if defined(_Field_size_bytes_part_opt_) && defined(SALIERI_DEFINED_Field_size_bytes_part_opt)\n#undef _Field_size_bytes_part_opt_\n#endif\n#if !defined(_Field_size_bytes_part_opt_)\n#define _Field_size_bytes_part_opt_(size, count)\n#define SALIERI_DEFINED_Field_size_bytes_part_opt\n#endif\n\n#if defined(_Field_size_full_) && defined(SALIERI_DEFINED_Field_size_full)\n#undef _Field_size_full_\n#endif\n#if !defined(_Field_size_full_)\n#define _Field_size_full_(size)\n#define SALIERI_DEFINED_Field_size_full\n#endif\n\n#if defined(_Field_size_full_opt_) && defined(SALIERI_DEFINED_Field_size_full_opt)\n#undef _Field_size_full_opt_\n#endif\n#if !defined(_Field_size_full_opt_)\n#define _Field_size_full_opt_(size)\n#define SALIERI_DEFINED_Field_size_full_opt\n#endif\n\n#if defined(_Field_size_bytes_full_) && defined(SALIERI_DEFINED_Field_size_bytes_full)\n#undef _Field_size_bytes_full_\n#endif\n#if !defined(_Field_size_bytes_full_)\n#define _Field_size_bytes_full_(size)\n#define SALIERI_DEFINED_Field_size_bytes_full\n#endif\n\n#if defined(_Field_size_bytes_full_opt_) && defined(SALIERI_DEFINED_Field_size_bytes_full_opt)\n#undef _Field_size_bytes_full_opt_\n#endif\n#if !defined(_Field_size_bytes_full_opt_)\n#define _Field_size_bytes_full_opt_(size)\n#define SALIERI_DEFINED_Field_size_bytes_full_opt\n#endif\n\n#if defined(_Struct_size_bytes_) && defined(SALIERI_DEFINED_Struct_size_bytes)\n#undef _Struct_size_bytes_\n#endif\n#if !defined(_Struct_size_bytes_)\n#define _Struct_size_bytes_(size)\n#define SALIERI_DEFINED_Struct_size_bytes\n#endif\n\n/* Annotating Locking Behavior\n *\n * https://msdn.microsoft.com/en-us/library/hh916381.aspx\n *****/\n\n#if defined(_Acquires_exclusive_lock_) && defined(SALIERI_DEFINED_Acquires_exclusive_lock)\n#undef _Acquires_exclusive_lock_\n#endif\n#if !defined(_Acquires_exclusive_lock_)\n#define _Acquires_exclusive_lock_(expr)\n#define SALIERI_DEFINED_Acquires_exclusive_lock\n#endif\n\n#if defined(_Acquires_lock_) && defined(SALIERI_DEFINED_Acquires_lock)\n#undef _Acquires_lock_\n#endif\n#if !defined(_Acquires_lock_)\n#define _Acquires_lock_(expr)\n#define SALIERI_DEFINED_Acquires_lock\n#endif\n\n#if defined(_Acquires_nonreentrant_lock_) && defined(SALIERI_DEFINED_Acquires_nonreentrant_lock)\n#undef _Acquires_nonreentrant_lock_\n#endif\n#if !defined(_Acquires_nonreentrant_lock_)\n#define _Acquires_nonreentrant_lock_(expr)\n#define SALIERI_DEFINED_Acquires_nonreentrant_lock\n#endif\n\n#if defined(_Acquires_shared_lock_) && defined(SALIERI_DEFINED_Acquires_shared_lock)\n#undef _Acquires_shared_lock_\n#endif\n#if !defined(_Acquires_shared_lock_)\n#define _Acquires_shared_lock_(expr)\n#define SALIERI_DEFINED_Acquires_shared_lock\n#endif\n\n#if defined(_Create_lock_level_) && defined(SALIERI_DEFINED_Create_lock_level)\n#undef _Create_lock_level_\n#endif\n#if !defined(_Create_lock_level_)\n#define _Create_lock_level_(name)\n#define SALIERI_DEFINED_Create_lock_level\n#endif\n\n#if defined(_Has_lock_kind_) && defined(SALIERI_DEFINED_Has_lock_kind)\n#undef _Has_lock_kind_\n#endif\n#if !defined(_Has_lock_kind_)\n#define _Has_lock_kind_(kind)\n#define SALIERI_DEFINED_Has_lock_kind\n#endif\n\n#if defined(_Has_lock_level_) && defined(SALIERI_DEFINED_Has_lock_level)\n#undef _Has_lock_level_\n#endif\n#if !defined(_Has_lock_level_)\n#define _Has_lock_level_(name)\n#define SALIERI_DEFINED_Has_lock_level\n#endif\n\n#if defined(_Lock_level_order_) && defined(SALIERI_DEFINED_Lock_level_order)\n#undef _Lock_level_order_\n#endif\n#if !defined(_Lock_level_order_)\n#define _Lock_level_order_(name1, name2)\n#define SALIERI_DEFINED_Lock_level_order\n#endif\n\n#if defined(_Post_same_lock_) && defined(SALIERI_DEFINED_Post_same_lock)\n#undef _Post_same_lock_\n#endif\n#if !defined(_Post_same_lock_)\n#define _Post_same_lock_(expr1, expr2)\n#define SALIERI_DEFINED_Post_same_lock\n#endif\n\n#if defined(_Releases_exclusive_lock_) && defined(SALIERI_DEFINED_Releases_exclusive_lock)\n#undef _Releases_exclusive_lock_\n#endif\n#if !defined(_Releases_exclusive_lock_)\n#define _Releases_exclusive_lock_(expr)\n#define SALIERI_DEFINED_Releases_exclusive_lock\n#endif\n\n#if defined(_Releases_lock_) && defined(SALIERI_DEFINED_Releases_lock)\n#undef _Releases_lock_\n#endif\n#if !defined(_Releases_lock_)\n#define _Releases_lock_(expr)\n#define SALIERI_DEFINED_Releases_lock\n#endif\n\n#if defined(_Releases_nonreentrant_lock_) && defined(SALIERI_DEFINED_Releases_nonreentrant_lock)\n#undef _Releases_nonreentrant_lock_\n#endif\n#if !defined(_Releases_nonreentrant_lock_)\n#define _Releases_nonreentrant_lock_(expr)\n#define SALIERI_DEFINED_Releases_nonreentrant_lock\n#endif\n\n#if defined(_Releases_shared_lock_) && defined(SALIERI_DEFINED_Releases_shared_lock)\n#undef _Releases_shared_lock_\n#endif\n#if !defined(_Releases_shared_lock_)\n#define _Releases_shared_lock_(expr)\n#define SALIERI_DEFINED_Releases_shared_lock\n#endif\n\n#if defined(_Requires_lock_held_) && defined(SALIERI_DEFINED_Requires_lock_held)\n#undef _Requires_lock_held_\n#endif\n#if !defined(_Requires_lock_held_)\n#define _Requires_lock_held_(expr)\n#define SALIERI_DEFINED_Requires_lock_held\n#endif\n\n#if defined(_Requires_lock_not_held_) && defined(SALIERI_DEFINED_Requires_lock_not_held)\n#undef _Requires_lock_not_held_\n#endif\n#if !defined(_Requires_lock_not_held_)\n#define _Requires_lock_not_held_(expr)\n#define SALIERI_DEFINED_Requires_lock_not_held\n#endif\n\n#if defined(_Requires_no_locks_held_) && defined(SALIERI_DEFINED_Requires_no_locks_held)\n#undef _Requires_no_locks_held_\n#endif\n#if !defined(_Requires_no_locks_held_)\n#define _Requires_no_locks_held_\n#define SALIERI_DEFINED_Requires_no_locks_held\n#endif\n\n#if defined(_Requires_shared_lock_held_) && defined(SALIERI_DEFINED_Requires_shared_lock_held)\n#undef _Requires_shared_lock_held_\n#endif\n#if !defined(_Requires_shared_lock_held_)\n#define _Requires_shared_lock_held_(expr)\n#define SALIERI_DEFINED_Requires_shared_lock_held\n#endif\n\n#if defined(_Requires_exclusive_lock_held_) && defined(SALIERI_DEFINED_Requires_exclusive_lock_held)\n#undef _Requires_exclusive_lock_held_\n#endif\n#if !defined(_Requires_exclusive_lock_held_)\n#define _Requires_exclusive_lock_held_(expr)\n#define SALIERI_DEFINED_Requires_exclusive_lock_held\n#endif\n\n/* Shared Data Access Annotations */\n\n#if defined(_Guarded_by_) && defined(SALIERI_DEFINED_Guarded_by)\n#undef _Guarded_by_\n#endif\n#if !defined(_Guarded_by_)\n#define _Guarded_by_(expr)\n#define SALIERI_DEFINED_Guarded_by\n#endif\n\n#if defined(_Interlocked_) && defined(SALIERI_DEFINED_Interlocked)\n#undef _Interlocked_\n#endif\n#if !defined(_Interlocked_)\n#define _Interlocked_\n#define SALIERI_DEFINED_Interlocked\n#endif\n\n#if defined(_Interlocked_operand_) && defined(SALIERI_DEFINED_Interlocked_operand)\n#undef _Interlocked_operand_\n#endif\n#if !defined(_Interlocked_operand_)\n#define _Interlocked_operand_\n#define SALIERI_DEFINED_Interlocked_operand\n#endif\n\n#if defined(_Write_guarded_by_) && defined(SALIERI_DEFINED_Write_guarded_by)\n#undef _Write_guarded_by_\n#endif\n#if !defined(_Write_guarded_by_)\n#define _Write_guarded_by_(expr)\n#define SALIERI_DEFINED_Write_guarded_by\n#endif\n\n/* Specifying When and Where an Annotation Applies\n *\n * https://msdn.microsoft.com/en-us/library/jj159526.aspx\n *****/\n\n#if defined(_At_) && defined(SALIERI_DEFINED_At)\n#undef _At_\n#endif\n#if !defined(_At_)\n#define _At_(expr, anno_list)\n#define SALIERI_DEFINED_At\n#endif\n\n#if defined(_At_buffer_) && defined(SALIERI_DEFINED_At_buffer)\n#undef _At_buffer_\n#endif\n#if !defined(_At_buffer_)\n#define _At_buffer_(expr, iter, elem_count, anno_list)\n#define SALIERI_DEFINED_At_buffer\n#endif\n\n#if defined(_Group_) && defined(SALIERI_DEFINED_Group)\n#undef _Group_\n#endif\n#if !defined(_Group_)\n#define _Group_(anno_list)\n#define SALIERI_DEFINED_Group\n#endif\n\n#if defined(_When_) && defined(SALIERI_DEFINED_When)\n#undef _When_\n#endif\n#if !defined(_When_)\n#define _When_(expr, anno_list)\n#define SALIERI_DEFINED_When\n#endif\n\n/* Intrinsic Functions\n *\n * https://msdn.microsoft.com/en-us/library/jj159527.aspx\n *****/\n\n/* General Purpose */\n\n#if defined(_Curr_) && defined(SALIERI_DEFINED_Curr)\n#undef _Curr_\n#endif\n#if !defined(_Curr_)\n#define _Curr_\n#define SALIERI_DEFINED_Curr\n#endif\n\n#if defined(_Inexpressible_) && defined(SALIERI_DEFINED_Inexpressible)\n#undef _Inexpressible_\n#endif\n#if !defined(_Inexpressible_)\n#define _Inexpressible_(expr)\n#define SALIERI_DEFINED_Inexpressible\n#endif\n\n#if defined(_Nullterm_length_) && defined(SALIERI_DEFINED_Nullterm_length)\n#undef _Nullterm_length_\n#endif\n#if !defined(_Nullterm_length_)\n#define _Nullterm_length_(param)\n#define SALIERI_DEFINED_Nullterm_length\n#endif\n\n#if defined(_Old_) && defined(SALIERI_DEFINED_Old)\n#undef _Old_\n#endif\n#if !defined(_Old_)\n#define _Old_(expr)\n#define SALIERI_DEFINED_Old\n#endif\n\n#if defined(_Param_) && defined(SALIERI_DEFINED_Param)\n#undef _Param_\n#endif\n#if !defined(_Param_)\n#define _Param_(n)\n#define SALIERI_DEFINED_Param\n#endif\n\n/* String Specific */\n\n#if defined(_String_length_) && defined(SALIERI_DEFINED_String_length)\n#undef _String_length_\n#endif\n#if !defined(_String_length_)\n#define _String_length_(param)\n#define SALIERI_DEFINED_String_length\n#endif\n\n#if defined(SALIERI_VERSION)\n#undef SALIERI_VERSION\n#endif\n\n#define SALIERI_VERSION 1\n\n#endif /* !defined(SALIERI_VERSION) || (SALIERI_VERSION < X) */\n"
  },
  {
    "path": "wolf/ml/referee_ocr/w_image_processor.cpp",
    "content": "#include \"w_image_processor.hpp\"\n\n#include \"salieri.h\"\n\n// using config_for_ocr_struct = wolf::ml::ocr::config_for_ocr_struct;\n// using gaussian_blur = wolf::ml::ocr::gaussian_blur;\n// using make_contour_white_background =\n//     wolf::ml::ocr::make_contour_white_background;\n// using negative_image = wolf::ml::ocr::negative_image;\n// using prepare_image_for_contour_detection =\n//     wolf::ml::ocr::prepare_image_for_contour_detection;\n// using resize_image = wolf::ml::ocr::resize_image;\n// using threshold_image = wolf::ml::ocr::threshold_image;\n// using config_for_ocr_struct = wolf::ml::ocr::config_for_ocr_struct;\n// using namespace wolf::ml::ocr;\n\nnamespace wolf::ml::ocr {\n\nstd::vector<std::vector<cv::Point>>\nfind_all_countors(_In_ cv::Mat &filtered_image) {\n  std::vector<std::vector<cv::Point>> contours;\n  std::vector<cv::Vec4i> hierarchy;\n\n  cv::findContours(filtered_image, contours, hierarchy, cv::RETR_TREE,\n                   cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));\n\n  return contours;\n}\n\nvoid gaussian_blur(_Inout_ cv::Mat &frame_box,\n                   _In_ config_for_ocr_struct &ocr_config) {\n  int kernel_size = ocr_config.gaussian_blur_win_size;\n  cv::GaussianBlur(frame_box, frame_box, cv::Size(kernel_size, kernel_size), 0,\n                   0);\n}\n\nvoid make_contour_white_background(_Inout_ cv::Mat &contour_image,\n                                   _In_ config_for_ocr_struct &ocr_config) {\n  int height = contour_image.rows;\n  int width = contour_image.cols;\n  int n_channels = contour_image.channels();\n\n  if (ocr_config.make_white_background) {\n    if (n_channels == 1) {\n      for (int i = 0; i < height; i++) {\n        for (int j = 0; j < width; j++) {\n          if (contour_image.at<uchar>(i, j) >\n              ocr_config.white_background_threshold) {\n            contour_image.at<uchar>(i, j) = 180;\n          }\n        }\n      }\n    } else if (n_channels == 3) {\n      for (int i = 0; i < height; i++) {\n        for (int j = 0; j < width; j++) {\n          cv::Vec3b &color_pixel = contour_image.at<cv::Vec3b>(i, j);\n          int count = 0, combine = 0;\n          for (int i = 0; i < 3; i++) {\n            if (color_pixel[i] > ocr_config.white_background_threshold) {\n              count++;\n              combine += color_pixel[i];\n            }\n          }\n          if (count > 2 ||\n              combine > ocr_config.white_background_threshold * 2 + 100) {\n            color_pixel[0] =\n                255; // (color_pixel[0]*2 > 255) ? 255:color_pixel[0];\n            color_pixel[1] =\n                255; // (color_pixel[1]*2 > 255) ? 255:color_pixel[1];\n            color_pixel[2] =\n                255; // (color_pixel[2]*2 > 255) ? 255:color_pixel[2];\n          }\n        }\n      }\n    }\n  }\n}\n\nvoid negative_image(_Inout_ cv::Mat &contour_image) {\n  int height = contour_image.rows;\n  int width = contour_image.cols;\n  int n_channels = contour_image.channels();\n\n  if (n_channels == 1) {\n    for (int i = 0; i < height; i++) {\n      for (int j = 0; j < width; j++) {\n        contour_image.at<uchar>(i, j) = 255 - contour_image.at<uchar>(i, j);\n      }\n    }\n  } else if (n_channels == 3) {\n    for (int i = 0; i < height; i++) {\n      for (int j = 0; j < width; j++) {\n        cv::Vec3b &color_pixel = contour_image.at<cv::Vec3b>(i, j);\n        color_pixel[0] = 255 - color_pixel[0];\n        color_pixel[1] = 255 - color_pixel[1];\n        color_pixel[2] = 255 - color_pixel[2];\n      }\n    }\n  }\n}\n\ncv::Mat\nprepare_image_for_contour_detection(_In_ cv::Mat &image,\n                                    _In_ config_for_ocr_struct &ocr_config) {\n  cv::Mat filtered_image = image.clone();\n  if (ocr_config.do_resize) {\n    int dist_height = ocr_config.resized_height;\n    resize_image(filtered_image, dist_height);\n  }\n\n  if (ocr_config.do_blur) {\n    gaussian_blur(filtered_image, ocr_config);\n  }\n\n  if (ocr_config.do_threshold) {\n    threshold_image(filtered_image, ocr_config);\n  }\n  return filtered_image;\n}\n\nvoid resize_image(_Inout_ cv::Mat &frame_box, _In_ int dest_height,\n                  _In_ int dest_width) {\n  /*!<fraction = 1.0*/\n  float ratio;\n  cv::Size dim;\n\n  int frame_height = frame_box.rows;\n  int frame_width = frame_box.cols;\n\n  if (dest_width == -1 && dest_height == -1) {\n    return;\n  }\n\n  if (dest_width == -1) {\n    ratio = float(dest_height) / float(frame_height);\n    dim.width = int(frame_width * ratio);\n    dim.height = dest_height;\n    // fraction = r;\n  } else {\n    ratio = float(dest_width) / float(frame_width);\n    dim.width = dest_width;\n    dim.height = int(frame_height * ratio);\n    // fraction = r;\n  }\n  cv::resize(frame_box, frame_box, dim);\n}\n\nvoid threshold_image(_Inout_ cv::Mat &frame_box,\n                     _In_ config_for_ocr_struct &ocr_config) {\n  if (frame_box.channels() == 3) {\n    if (ocr_config.binary) {\n      cv::cvtColor(frame_box, frame_box, cv::COLOR_BGR2GRAY);\n      cv::threshold(frame_box, frame_box, 0, 255, cv::THRESH_OTSU);\n      cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3),\n                                                 cv::Point(0, 0));\n\n      cv::morphologyEx(frame_box, frame_box, cv::MORPH_CLOSE, kernel);\n    } else {\n      cv::inRange(frame_box,\n                  cv::Scalar(ocr_config.threshold_value,\n                             ocr_config.threshold_value,\n                             ocr_config.threshold_value),\n                  cv::Scalar(255, 255, 255), frame_box);\n    }\n  } else if (frame_box.channels() == 1) {\n    cv::threshold(frame_box, frame_box, ocr_config.threshold_value, 255,\n                  cv::THRESH_BINARY);\n  }\n  // return image;\n}\n} // namespace wolf::ml::ocr\n"
  },
  {
    "path": "wolf/ml/referee_ocr/w_image_processor.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <opencv2/opencv.hpp>\n#include <string>\n#include <vector>\n\n#include \"salieri.h\"\n\n/*! \\brief This class is responsible for image processing tasks.\n\n        This class contains functions, structures, and variables that use for\n   image processing purposes. In the project, in other classes, in the case of\n   processing image, one must create an object of the ImageProcessing class.\n*/\n\nnamespace wolf::ml::ocr {\n\n//! Restriction struct.\n/*!\n                Characters must satisfy the struct restrictions.\n        */\nstruct restrictions_struct {\n  int min_area;\n  int max_area;\n  int min_height;\n  int max_height;\n  int min_width;\n  int max_width;\n};\n\n//! OCR configuration struct.\n/*!\n                The necessary configurations for processing optical characters.\n        */\nstruct config_for_ocr_struct {\n  /*!<If true, then the input image box change to the binary form.*/\n  bool binary = false;\n  /*!<The best height for processing. depend on the model.*/\n  int desired_contour_height = 32;\n  /*!<If true, it means the frame should be blurred.*/\n  bool do_blur = true;\n  /*!<The image box would be resized by the factor.*/\n  bool do_resize = false;\n  /*!<If true, it means the contour should be resized.*/\n  bool do_resize_contour = false;\n  /*!<If true, it means the frame should be thresholded.*/\n  bool do_threshold = true;\n  /*!<This fraction applies to finding out the space between two characters.*/\n  double fraction = 0.9;\n  /*!<Gaussian kernel size. the size must be positive and odd.*/\n  int gaussian_blur_win_size = 3;\n  /*!<If true, we are storing the image boxes*/\n  bool if_store_image_boxes = false;\n  /*!<If the character is white, then set it true.*/\n  bool is_white = true;\n  /*!<If the character is number, then set it true.*/\n  bool is_digit = true;\n  /*!<If the background needs to be white, then set it true.*/\n  bool make_white_background = false;\n  /*!<The margin between a character contour and the image window box.*/\n  int margin = 6;\n  /*!<The debugging path*/\n  std::string ocr_debug_path = \"../../database/ocr_debug_data\";\n  /*!<The contours with overlap more than this threshold would be combined.*/\n  double overlapped_threshold = 0.2;\n  /*!<Apply to resizing the image boxes.*/\n  double resized_fraction = 1.0;\n  /*!<The maximum height for an image window.*/\n  int resized_height = 40;\n  /*!<The maximum height for an image window.*/\n  int resized_width = 40;\n  /*!<The pixels with a value greater than the threshold change to 255.*/\n  int threshold_value = 110;\n  /*!<If true, then image converts to grayscale*/\n  bool to_gray = true;\n  /*!<If true, during the code execution some extra log would be shown.*/\n  bool verbose = false;\n  /*!<The character's background should be white.*/\n  int white_background_threshold = 150;\n  /*!<Characters must satisfy the struct restrictions.*/\n  restrictions_struct restrictions;\n};\n\n/*!\n        Find all contours in filtered image.\n        \\param  filtered_image    The image needs to be processed.\n        \\return vector of contours..\n        */\nstd::vector<std::vector<cv::Point>>\nfind_all_countors(_In_ cv::Mat &filtered_image);\n\n/*!\n        blur image by specified configuration\n        \\param  frame_box    The image needs to be processed.\n        \\param  ocr_config    The necessary configurations for processing\n   optical characters.\n        */\nvoid gaussian_blur(_Inout_ cv::Mat &frame_box,\n                   _In_ config_for_ocr_struct &ocr_config);\n\n/*!\n        takes an image and makes the background white. this function uses a\n   threshold to find background points \\param  contour_image    The image needs\n   to be processed. \\param  ocr_config    The necessary configurations for\n   processing optical characters.\n        */\nvoid make_contour_white_background(_Inout_ cv::Mat &contour_image,\n                                   _In_ config_for_ocr_struct &ocr_config);\n\n/*!\n          The negative_image function changed the pixels' value. The new value\n   is obtained by 255 - the previous value.\n\n          \\param  contour_image    contour_image is a cropped part of the\n   original image that contains one of the contours.\n        */\nvoid negative_image(_Inout_ cv::Mat &contour_image);\n\n/*!\n          apply some filters to better find contours.\n\n          \\param  image    The image needs to be processed.\n          \\param  ocr_config    The necessary configurations for processing\n   optical characters.\n        */\ncv::Mat\nprepare_image_for_contour_detection(_In_ cv::Mat &image,\n                                    _In_ config_for_ocr_struct &ocr_config);\n\n/*!\n          resize image to specified size.\n          \\param  frame_box    The image needs to be processed.\n          \\param  dest_height    The height of destination image.\n          \\param  dest_width    The width of destination image.\n        */\nvoid resize_image(_Inout_ cv::Mat &frame_box, _In_ int dest_height = -1,\n                  _In_ int dest_width = -1);\n\n/*!\n        The initial_filtering function prepares the input image for processing.\n        \\param  frame_box     The image needs to be processed.\n        \\param  ocr_config    The necessary configurations for processing\n   optical characters.\n        */\nvoid threshold_image(_Inout_ cv::Mat &frame_box,\n                     _In_ config_for_ocr_struct &ocr_config);\n\n} // namespace wolf::ml::ocr"
  },
  {
    "path": "wolf/ml/referee_ocr/w_ocr_engine.cpp",
    "content": "#include \"w_ocr_engine.hpp\"\n\n#include <stdio.h>\n#include <string.h>\n#include <sys/stat.h>\n\n#include <cctype>\n#include <cstring>\n#include <filesystem>\n\n#include \"w_utilities.hpp\"\n\nnamespace fs = std::filesystem;\n\n#ifdef __TELEMETRY\n#include \"opentelemetry/sdk/version/version.h\"\n#include \"opentelemetry/trace/provider.h\"\n\nnamespace trace = opentelemetry::trace;\nnamespace nostd = opentelemetry::nostd;\n\nnamespace {\nnostd::shared_ptr<trace::Tracer> get_tracer() {\n  auto provider = trace::Provider::GetTracerProvider();\n  return provider->GetTracer(\"pes_21\", OPENTELEMETRY_SDK_VERSION);\n}\n} // namespace\n#endif\n\nusing w_ocr_engine = wolf::ml::ocr::w_ocr_engine;\nusing config_for_ocr_struct = wolf::ml::ocr::config_for_ocr_struct;\n\nw_ocr_engine::w_ocr_engine() {\n  std::string key = \"TESSERACT_LOG\";\n  std::string tesseract_log = get_env_string(key.c_str());\n\n  digit_api->Init(nullptr, \"eng\", tesseract::OEM_LSTM_ONLY);\n  digit_api->SetPageSegMode(tesseract::PSM_SINGLE_CHAR);\n  digit_api->SetVariable(\"tessedit_char_whitelist\", \"0123456789\");\n  digit_api->SetVariable(\"user_defined_dpi\", \"70\");\n  digit_api->SetVariable(\"debug_file\", tesseract_log.c_str());\n\n  word_api->Init(nullptr, \"eng\", tesseract::OEM_LSTM_ONLY);\n  word_api->SetPageSegMode(tesseract::PSM_SINGLE_CHAR);\n  word_api->SetVariable(\n      \"tessedit_char_whitelist\",\n      \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"); //\t,\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n                                                               //// ,\n  word_api->SetVariable(\"user_defined_dpi\", \"70\");\n  word_api->SetVariable(\"debug_file\", tesseract_log.c_str());\n}\n\nw_ocr_engine::~w_ocr_engine() {\n  digit_api->End();\n  word_api->End();\n}\n\nbool w_ocr_engine::check_if_overlapped(_In_ cv::Rect box_1, _In_ cv::Rect box_2,\n                                       _In_ config_for_ocr_struct &ocr_config) {\n  bool if_overlapped = false;\n  int area_1, area_2, overlapped_area;\n\n  int dx = std::min(box_1.x + box_1.width, box_2.x + box_2.width) -\n           std::max(box_1.x, box_2.x);\n  int dy = std::min(box_1.y + box_1.height, box_2.y + box_2.height) -\n           std::max(box_1.y, box_2.y);\n\n  if (dx > 0 && dy > 0) {\n    area_1 = box_1.width * box_1.height;\n    area_2 = box_2.width * box_2.height;\n\n    overlapped_area = dx * dy;\n\n    if (double(overlapped_area) / double(area_1) >\n            ocr_config.overlapped_threshold ||\n        double(overlapped_area) / double(area_2) >\n            ocr_config.overlapped_threshold) {\n      if_overlapped = true;\n    }\n  }\n\n  return if_overlapped;\n}\n\n// this function is related to cluster_char_structs function\nbool compare_char_by_x_position(\n    const w_ocr_engine::characters_struct &first_charactor,\n    const w_ocr_engine::characters_struct &second_charactor) {\n  return first_charactor.center.x < second_charactor.center.x;\n}\n\nstd::vector<w_ocr_engine::characters_struct>\nw_ocr_engine::contours_to_char_structs(\n    _In_ std::vector<std::vector<cv::Point>> contours) {\n  std::vector<characters_struct> modified_contours;\n  size_t number_of_contours = contours.size();\n\n  for (size_t i = 0; i < number_of_contours; i++) {\n    std::vector<cv::Point> contour_poly;\n    characters_struct temp_modified_contour;\n    temp_modified_contour.contour = contours[i];\n\n    double epsilon = 3;\n    bool closed = true;\n    cv::approxPolyDP(cv::Mat(contours[i]), contour_poly, epsilon, closed);\n\n    temp_modified_contour.bound_rect = cv::boundingRect(cv::Mat(contour_poly));\n\n    contour_poly.clear();\n    temp_modified_contour.center.x = temp_modified_contour.bound_rect.x +\n                                     temp_modified_contour.bound_rect.width / 2;\n\n    temp_modified_contour.center.y =\n        temp_modified_contour.bound_rect.y +\n        temp_modified_contour.bound_rect.height / 2;\n\n    temp_modified_contour.height = temp_modified_contour.bound_rect.height;\n\n    modified_contours.push_back(temp_modified_contour);\n  }\n  return modified_contours;\n}\n\nvoid w_ocr_engine::enhance_contour_image_for_model(\n    _Inout_ cv::Mat &contour_image, _In_ config_for_ocr_struct &ocr_config) {\n  if (!(ocr_config.make_white_background || ocr_config.do_resize_contour)) {\n    return;\n  }\n\n  if (ocr_config.make_white_background) {\n    make_contour_white_background(contour_image, ocr_config);\n  }\n\n  if (ocr_config.do_resize_contour) {\n    // float resize_fraction =\n    // float(ocr_config.desired_contour_height)/float(height);\n    int dist_height = ocr_config.desired_contour_height;\n    int dist_width = 24; // int(resize_fraction*width);\n\n    cv::resize(contour_image, contour_image, cv::Size(dist_width, dist_height),\n               0.0, 0.0, cv::InterpolationFlags::INTER_AREA);\n  }\n\n  return;\n}\n\ndouble w_ocr_engine::euclidean_distance(characters_struct &first_character,\n                                        characters_struct &second_character) {\n  double dist_x = std::pow(\n      float(first_character.center.x - second_character.center.x), 2.0);\n  double dist_y = std::pow(\n      float(first_character.center.y - second_character.center.y), 2.0);\n  double dist = std::pow(dist_x + dist_y, 0.5);\n\n  return dist;\n}\n\nauto w_ocr_engine::euclidean_distance(int x1, int x2, int y1, int y2)\n    -> double {\n  double dist_x = std::pow(float(x1 - x2), 2.0);\n  double dist_y = std::pow(float(y1 - y2), 2.0);\n  double dist = std::pow(dist_x + dist_y, 0.5);\n\n  return dist;\n}\n\nauto w_ocr_engine::spaces_between_two_chars(characters_struct left_char,\n                                            characters_struct right_char,\n                                            float height_to_dist_ratio)\n    -> std::string {\n  std::string temp_spaces = \"\";\n\n  int left_char_right_corner =\n      left_char.bound_rect.x + left_char.bound_rect.width;\n  int right_char_left_corner = right_char.bound_rect.x;\n\n  if (right_char_left_corner - left_char_right_corner > 0) {\n    if (float(right_char_left_corner - left_char_right_corner) >\n        float(left_char.bound_rect.height) * height_to_dist_ratio) {\n      temp_spaces = \"  \";\n    } else {\n      temp_spaces = \" \";\n    }\n  }\n\n  return temp_spaces;\n}\n\nstd::vector<w_ocr_engine::character_and_center>\nw_ocr_engine::char_clusters_to_text(\n    std::vector<std::vector<characters_struct>> clustered_characters) {\n  std::vector<w_ocr_engine::character_and_center> words;\n\n  for (size_t i = 0; i < clustered_characters.size(); i++) {\n    std::sort(clustered_characters[i].begin(), clustered_characters[i].end());\n    character_and_center temp;\n    temp.center = clustered_characters[i][0].center;\n\n    std::string spaces = \"\";\n    float height_to_dist_ratio =\n        get_env_float(\"SOCCER_GLOBAL_HEIGHT_TO_DIST_RATIO\");\n\n    for (size_t j = 0; j < clustered_characters[i].size(); j++) {\n      std::string temp_string =\n          split_string(clustered_characters[i][j].text, '\\n')[0];\n      if (j < clustered_characters[i].size() - 1) {\n        spaces = spaces_between_two_chars(clustered_characters[i][j],\n                                          clustered_characters[i][j + 1],\n                                          height_to_dist_ratio);\n      }\n      temp_string += spaces;\n      temp.text.append(temp_string);\n    }\n\n    std::transform(temp.text.begin(), temp.text.end(), temp.text.begin(),\n                   ::toupper);\n\n    words.push_back(temp);\n  }\n\n  clustered_characters.clear();\n\n  std::sort(words.begin(), words.end());\n  return words;\n}\n\nstd::vector<w_ocr_engine::characters_struct>\nw_ocr_engine::filter_chars_by_contour_size(\n    _Inout_ std::vector<characters_struct> &character,\n    _In_ config_for_ocr_struct &ocr_config) {\n  std::vector<characters_struct> filtered_characters;\n  for (int i = 0; i < character.size(); i++) {\n    double area = cv::contourArea(character[i].contour);\n    if (area < ocr_config.restrictions.min_area ||\n        area > ocr_config.restrictions.max_area) {\n      continue;\n    }\n    if (character[i].bound_rect.height < ocr_config.restrictions.min_height ||\n        character[i].bound_rect.height > ocr_config.restrictions.max_height ||\n        character[i].bound_rect.width < ocr_config.restrictions.min_width ||\n        character[i].bound_rect.width > ocr_config.restrictions.max_width) {\n      continue;\n    }\n    filtered_characters.push_back(character[i]);\n  }\n  return filtered_characters;\n}\n\nstd::vector<w_ocr_engine::characters_struct>\nw_ocr_engine::image_to_char_structs(_In_ cv::Mat &image_box,\n                                    _In_ config_for_ocr_struct &ocr_config) {\n  cv::Mat filtered_image =\n      prepare_image_for_contour_detection(image_box, ocr_config);\n\n  std::vector<std::vector<cv::Point>> contours =\n      find_all_countors(filtered_image);\n  std::vector<characters_struct> characters =\n      contours_to_char_structs(contours);\n\n  std::vector<characters_struct> filtered_characters =\n      filter_chars_by_contour_size(characters, ocr_config);\n\n  merge_overlapped_contours(filtered_characters, ocr_config);\n\n  for (size_t i = 0; i < filtered_characters.size(); i++) {\n    margin_bounding_rect(filtered_characters[i].bound_rect, ocr_config.margin,\n                         filtered_image);\n  }\n\n  // TODO add this log \"This code has not been optimized for color image, yet\"\n  // << std::endl;\n  return filtered_characters;\n}\n\nauto w_ocr_engine::char_vec_to_string(\n    _In_ std::vector<w_ocr_engine::characters_struct> char_vector,\n    _In_ cv::Mat &frame, _In_ config_for_ocr_struct &ocr_config)\n    -> std::vector<character_and_center> {\n  std::vector<w_ocr_engine::characters_struct> labeled_characters =\n      label_chars_in_char_structs(char_vector, frame, ocr_config);\n  std::vector<std::vector<w_ocr_engine::characters_struct>>\n      clustered_characters =\n          cluster_char_structs(labeled_characters, ocr_config);\n  std::vector<w_ocr_engine::character_and_center> string =\n      char_clusters_to_text(clustered_characters);\n\n  return string;\n}\n\nstd::vector<w_ocr_engine::character_and_center>\nw_ocr_engine::image_to_string(_In_ cv::Mat &image,\n                              _In_ config_for_ocr_struct &ocr_config) {\n  std::vector<characters_struct> characters =\n      image_to_char_structs(image, ocr_config);\n  std::vector<characters_struct> labeled_characters =\n      label_chars_in_char_structs(characters, image, ocr_config);\n  std::vector<std::vector<characters_struct>> clustered_characters =\n      cluster_char_structs(labeled_characters, ocr_config);\n  std::vector<character_and_center> string =\n      char_clusters_to_text(clustered_characters);\n\n  return string;\n}\n\nstd::vector<w_ocr_engine::characters_struct>\nw_ocr_engine::label_chars_in_char_structs(\n    _In_ std::vector<w_ocr_engine::characters_struct> &characters,\n    _In_ cv::Mat &image_box, _In_ config_for_ocr_struct &ocr_config) {\n  std::vector<characters_struct> labeled_chars;\n  tesseract::TessBaseAPI *tess_api;\n  if (ocr_config.is_digit) {\n    tess_api = digit_api;\n  } else {\n    tess_api = word_api;\n  }\n\n  for (size_t i = 0; i < characters.size(); i++) {\n    cv::Mat temp_contour_image;\n    cv::Mat contour_image;\n    // Sometimes it is better to use the original image for w_ocr_engine\n    if (ocr_config.binary) {\n      cv::Mat filtered_image =\n          prepare_image_for_contour_detection(image_box, ocr_config);\n      filtered_image(characters[i].bound_rect).copyTo(contour_image);\n    } else {\n      // original_image(modified_bounding_rects[i].bound_rect).copyTo(contour_image);\n      contour_image = mask_contour(image_box, characters[i]);\n    }\n\n    if (ocr_config.is_white) {\n      negative_image(contour_image);\n    }\n\n    if (ocr_config.verbose) {\n      temp_contour_image = contour_image.clone();\n    }\n\n    enhance_contour_image_for_model(contour_image, ocr_config);\n    tess_api->SetImage(contour_image.data, contour_image.cols,\n                       contour_image.rows, 3, int(contour_image.step));\n\n    std::string text_data = tess_api->GetUTF8Text();\n\n    if (std::strcmp(text_data.c_str(), \"\") != 0) {\n      characters_struct temp_character;\n      temp_character = characters[i];\n      temp_character.text = split_string(text_data, '\\n')[0];\n\n      if (!temp_character.text.empty()) {\n        temp_character.text = temp_character.text.substr(0, 1);\n      }\n\n      labeled_chars.push_back(temp_character);\n    }\n    contour_image.release();\n    temp_contour_image.release();\n  }\n  return labeled_chars;\n}\n\nvoid w_ocr_engine::margin_bounding_rect(_Inout_ cv::Rect &bounding_rect,\n                                        _In_ int margin,\n                                        _In_ cv::Mat &filtered_image) {\n  int height = filtered_image.rows;\n  int width = filtered_image.cols;\n  int temp;\n  int temp_margin_width = int(std::ceil(float(margin) / 2));\n  int temp_margin_height = int(std::ceil(float(margin) / 2));\n\n  if (bounding_rect.width < 1 && margin > 0) {\n    temp_margin_width = 2;\n  }\n\n  if (bounding_rect.width < bounding_rect.height / 5) {\n    // temp = (bounding_rect.x - 1 * bounding_rect.width);\n    // bounding_rect.x = temp > 0 ? temp : 0;\n    // temp = (bounding_rect.x + 4 * bounding_rect.width);\n    // bounding_rect.width = temp < width ? 4 * bounding_rect.width : (width -\n    // bounding_rect.x - 1);\n    temp = (bounding_rect.x - 1 * bounding_rect.height / 6);\n    bounding_rect.x = temp > 0 ? temp : 0;\n    temp = (bounding_rect.x + bounding_rect.height);\n    bounding_rect.width =\n        temp < width ? bounding_rect.height / 2 : (width - bounding_rect.x - 1);\n  } else {\n    temp = (bounding_rect.x - temp_margin_width);\n    bounding_rect.x = temp > 0 ? temp : 0;\n    temp = (bounding_rect.x + bounding_rect.width + 3 * temp_margin_width);\n    bounding_rect.width = temp < width\n                              ? bounding_rect.width + 3 * temp_margin_width\n                              : (width - bounding_rect.x - 1);\n  }\n\n  temp = (bounding_rect.y - temp_margin_height);\n  bounding_rect.y = temp > 0 ? temp : 0;\n  temp = (bounding_rect.y + bounding_rect.height + 2 * temp_margin_height);\n  bounding_rect.height = temp < height\n                             ? bounding_rect.height + 2 * temp_margin_height\n                             : (height - bounding_rect.y - 1);\n}\n\ncv::Mat w_ocr_engine::mask_contour(_In_ cv::Mat &image,\n                                   _In_ characters_struct &contour_info) {\n  cv::Mat temp_plane_image =\n      cv::Mat(cv::Size(image.cols, image.rows), CV_8UC1, cv::Scalar(0));\n  cv::Mat mask_image;\n  cv::Mat contour_image;\n\n  std::vector<std::vector<cv::Point>> temp_contours;\n  temp_contours.push_back(contour_info.contour);\n  std::vector<std::vector<cv::Point>> hull(temp_contours.size());\n  for (unsigned int i = 0, n = temp_contours.size(); i < n; ++i) {\n    cv::convexHull(cv::Mat(temp_contours[i]), hull[i], false);\n  }\n  cv::drawContours(temp_plane_image, temp_contours, 0, cv::Scalar(255), 3);\n  cv::fillPoly(temp_plane_image, temp_contours, cv::Scalar(255));\n\n  temp_plane_image(contour_info.bound_rect).copyTo(mask_image);\n  image(contour_info.bound_rect).copyTo(contour_image, mask_image);\n\n  temp_plane_image.release();\n  mask_image.release();\n  return contour_image;\n}\n\nvoid w_ocr_engine::merge_overlapped_contours(\n    _Inout_ std::vector<characters_struct> &character,\n    _In_ config_for_ocr_struct &ocr_config) {\n  cv::Rect ref_box;\n  int index;\n  std::vector<int> overlapped_boxes_index;\n  // int width, height;\n\n  bool flag;\n  if (character.size() > 0) {\n    flag = true;\n  } else {\n    flag = false;\n  }\n\n  index = 0;\n  while (flag) {\n    ref_box = character[index].bound_rect;\n\n    overlapped_boxes_index.clear();\n    for (int i = 0; i < character.size(); i++) {\n      if (i == index) {\n        continue;\n      }\n      if (check_if_overlapped(ref_box, character[i].bound_rect, ocr_config)) {\n        overlapped_boxes_index.push_back(i);\n      }\n    }\n\n    for (int j = overlapped_boxes_index.size() - 1; j >= 0; j--) {\n      character[index].bound_rect.x =\n          std::min(character[index].bound_rect.x,\n                   character[overlapped_boxes_index[j]].bound_rect.x);\n      character[index].bound_rect.y =\n          std::min(character[index].bound_rect.y,\n                   character[overlapped_boxes_index[j]].bound_rect.y);\n      character[index].bound_rect.width =\n          std::max(character[index].bound_rect.x +\n                       character[index].bound_rect.width,\n                   character[overlapped_boxes_index[j]].bound_rect.x +\n                       character[overlapped_boxes_index[j]].bound_rect.width) -\n          character[index].bound_rect.x;\n      character[index].bound_rect.height =\n          std::max(character[index].bound_rect.y +\n                       character[index].bound_rect.height,\n                   character[overlapped_boxes_index[j]].bound_rect.y +\n                       character[overlapped_boxes_index[j]].bound_rect.height) -\n          character[index].bound_rect.y;\n      character.erase(character.begin() + int(overlapped_boxes_index[j]));\n    }\n\n    overlapped_boxes_index.clear();\n    if (index >= character.size() - 1) {\n      flag = false;\n    }\n\n    index++;\n  }\n}\n\nstd::vector<std::vector<w_ocr_engine::characters_struct>>\nw_ocr_engine::cluster_char_structs(\n    std::vector<w_ocr_engine::characters_struct> characters,\n    config_for_ocr_struct &ocr_config) {\n  std::vector<std::vector<characters_struct>> clustered_characters;\n\n  if (characters.size() == 0) {\n    return clustered_characters;\n  }\n\n  std::vector<characters_struct> temp_char_cluster;\n  std::vector<size_t> temp_index_list;\n  bool is_clustering;\n\n  temp_char_cluster.push_back(characters.back());\n  characters.pop_back();\n\n  if (characters.size() > 0) {\n    is_clustering = true;\n\n    while (is_clustering) {\n      for (size_t index = 0; index < characters.size(); index++) {\n        for (size_t i = 0; i < temp_char_cluster.size(); i++) {\n          if (~temp_char_cluster[i].processed) {\n            // double temp_dist = euclidean_distance(temp_char_cluster[i],\n            // characters[index]);\n\n            double temp_dist_1 =\n                euclidean_distance(temp_char_cluster[i].bound_rect.x,\n                                   characters[index].bound_rect.x +\n                                       characters[index].bound_rect.width,\n                                   temp_char_cluster[i].bound_rect.y +\n                                       temp_char_cluster[i].bound_rect.height,\n                                   characters[index].bound_rect.y +\n                                       characters[index].bound_rect.height);\n            double temp_dist_2 =\n                euclidean_distance(temp_char_cluster[i].bound_rect.x +\n                                       temp_char_cluster[i].bound_rect.width,\n                                   characters[index].bound_rect.x,\n                                   temp_char_cluster[i].bound_rect.y +\n                                       temp_char_cluster[i].bound_rect.height,\n                                   characters[index].bound_rect.y +\n                                       characters[index].bound_rect.height);\n\n            int temp_y_dist = std::abs(temp_char_cluster[i].bound_rect.y -\n                                       characters[index].bound_rect.y);\n\n            if ((temp_dist_1 < 0.8 * double(temp_char_cluster[i].height) ||\n                 temp_dist_2 < 0.8 * double(temp_char_cluster[i].height)) &&\n                temp_y_dist < temp_char_cluster[i].height) {\n              temp_index_list.push_back(index);\n              break;\n            }\n          }\n        }\n      }\n\n      for (size_t i = 0; i < temp_char_cluster.size(); i++) {\n        temp_char_cluster[i].processed = true;\n      }\n\n      if (temp_index_list.size() > 0) {\n        std::reverse(temp_index_list.begin(), temp_index_list.end());\n\n        for (size_t i = 0; i < temp_index_list.size(); i++) {\n          temp_char_cluster.push_back(characters[temp_index_list[i]]);\n          characters.erase(characters.begin() + int(temp_index_list[i]));\n        }\n\n        if (characters.size() == 0) {\n          clustered_characters.push_back(temp_char_cluster);\n          temp_char_cluster.clear();\n        }\n      } else {\n        clustered_characters.push_back(temp_char_cluster);\n        temp_char_cluster.clear();\n\n        temp_char_cluster.push_back(characters.back());\n        characters.pop_back();\n        if (characters.size() == 0) {\n          clustered_characters.push_back(temp_char_cluster);\n          temp_char_cluster.clear();\n        }\n      }\n\n      if (characters.size() == 0) {\n        is_clustering = false;\n      }\n\n      temp_index_list.clear();\n    }\n  } else {\n    clustered_characters.push_back(temp_char_cluster);\n    temp_char_cluster.clear();\n    // return;\n  }\n  return clustered_characters;\n}\n\ncv::Mat w_ocr_engine::show_in_better_way(cv::Mat &input_image,\n                                         int out_put_image_height,\n                                         float resize_factor) {\n  int height = out_put_image_height;\n  int width = height * 4 / 3;\n  cv::Mat temp_image;\n  if (resize_factor * input_image.rows > height) {\n    resize_factor = float(height / input_image.rows);\n  }\n  if (resize_factor * input_image.cols > width) {\n    resize_factor = float(width / input_image.cols);\n  }\n  if (input_image.channels() == 3) {\n    temp_image = cv::Mat(cv::Size(width, height), CV_8UC3, cv::Scalar(0, 0, 0));\n  } else {\n    temp_image = cv::Mat(cv::Size(width, height), CV_8UC1, cv::Scalar(0));\n  }\n\n  cv::Mat temp_contour = input_image.clone();\n  cv::resize(temp_contour, temp_contour,\n             cv::Size(input_image.cols * resize_factor,\n                      input_image.rows * resize_factor));\n  temp_contour.copyTo(\n      temp_image(cv::Rect(0, 0, input_image.cols * resize_factor,\n                          input_image.rows * resize_factor)));\n\n  temp_contour.release();\n  return temp_image;\n}\n\nstd::vector<std::string> w_ocr_engine::split_string(std::string input_string,\n                                                    char reference) {\n  std::stringstream test(input_string);\n  std::string segment;\n  std::vector<std::string> seglist;\n\n  while (std::getline(test, segment, reference)) {\n    seglist.push_back(segment);\n  }\n\n  return seglist;\n}\n\nauto w_ocr_engine::same_height(\n    _In_ std::vector<characters_struct> pClusteredChars) -> bool {\n  bool result = true;\n  int average_height = 0;\n\n  for (int i = 0; i < pClusteredChars.size(); i++) {\n    average_height += pClusteredChars[i].height;\n  }\n  average_height /= pClusteredChars.size();\n  int min_height = average_height - average_height / 5;\n  int max_height = average_height + average_height / 5;\n\n  for (int i = 0; i < pClusteredChars.size(); i++) {\n    if (pClusteredChars[i].height > max_height ||\n        pClusteredChars[i].height < min_height) {\n      result = false;\n    }\n  }\n\n  return result;\n}\n\nauto w_ocr_engine::same_level(\n    _In_ std::vector<characters_struct> pClusteredChars) -> bool {\n  bool result = true;\n  int average_height = 0;\n  int average_level = 0;\n\n  for (int i = 0; i < pClusteredChars.size(); i++) {\n    average_height += pClusteredChars[i].height;\n    average_level +=\n        pClusteredChars[i].bound_rect.y + pClusteredChars[i].bound_rect.height;\n  }\n  average_height /= pClusteredChars.size();\n  average_level /= pClusteredChars.size();\n  int min_level = average_level - average_height / 10;\n  int max_level = average_level + average_height / 10;\n\n  for (int i = 0; i < pClusteredChars.size(); i++) {\n    if (pClusteredChars[i].bound_rect.y + pClusteredChars[i].bound_rect.height >\n            max_level ||\n        pClusteredChars[i].bound_rect.y + pClusteredChars[i].bound_rect.height <\n            min_level) {\n      result = false;\n    }\n  }\n\n  return result;\n}\n\nauto w_ocr_engine::show_contours(\n    _Inout_ cv::Mat &pImage,\n    _In_ std::vector<characters_struct> pClusteredChars,\n    _In_ std::string pWindowName, _In_ bool pShow) -> void {\n  cv::Mat mask_image;\n\n  for (int i = 0; i < pClusteredChars.size(); i++) {\n    std::vector<std::vector<cv::Point>> temp_contours;\n    temp_contours.push_back(pClusteredChars[i].contour);\n    std::vector<std::vector<cv::Point>> hull(temp_contours.size());\n    for (unsigned int i = 0, n = temp_contours.size(); i < n; ++i) {\n      cv::convexHull(cv::Mat(temp_contours[i]), hull[i], false);\n    }\n    cv::drawContours(pImage, temp_contours, 0, cv::Scalar(255), 3);\n    cv::fillPoly(pImage, temp_contours, cv::Scalar(255));\n  }\n\n  if (pShow) {\n    cv::imshow(pWindowName, pImage);\n    cv::waitKey();\n  }\n\n  return;\n}\n\nauto w_ocr_engine::fill_cluster_features(\n    _Inout_ std::vector<characters_struct> &pClusteredChar,\n    _In_ int pImageWidth, _In_ int pIndex) -> cluster_features {\n  cluster_features features;\n\n  features.index_in_parent_vector = pIndex;\n\n  features.min_x = pClusteredChar[0].bound_rect.x;\n  features.max_x =\n      pClusteredChar[0].bound_rect.x + pClusteredChar[0].bound_rect.width;\n  features.min_y = pClusteredChar[0].bound_rect.y;\n  features.average_y = pClusteredChar[0].bound_rect.y;\n  features.average_height = pClusteredChar[0].bound_rect.height;\n\n  for (int i = 1; i < pClusteredChar.size(); i++) {\n    features.min_x = (features.min_x > pClusteredChar[i].bound_rect.x)\n                         ? pClusteredChar[i].bound_rect.x\n                         : features.min_x;\n    features.max_x = (features.max_x > pClusteredChar[i].bound_rect.x +\n                                           pClusteredChar[i].bound_rect.width)\n                         ? features.max_x\n                         : pClusteredChar[i].bound_rect.x +\n                               pClusteredChar[i].bound_rect.width;\n    features.min_y = (features.min_y > pClusteredChar[i].bound_rect.y)\n                         ? pClusteredChar[i].bound_rect.y\n                         : features.min_y;\n    features.average_y += pClusteredChar[0].bound_rect.y;\n    features.average_height += pClusteredChar[0].bound_rect.height;\n  }\n\n  features.average_y /= pClusteredChar.size();\n  features.average_height /= pClusteredChar.size();\n\n  int mid = pImageWidth / 2;\n  int temp1 = mid - features.min_x;\n  int temp2 = mid - features.max_x;\n\n  if (temp1 >= 0) {\n    if (temp2 > 0) {\n      features.position = cluster_position::left;\n      features.symmetric_x1 = temp2;\n      features.symmetric_x2 = temp1;\n    } else {\n      features.position = cluster_position::middle;\n      features.symmetric_x1 = 0;\n      features.symmetric_x2 = 0;\n    }\n  } else {\n    if (temp2 >= 0) {\n      features.position = cluster_position::middle;\n      features.symmetric_x1 = 0;\n      features.symmetric_x2 = 0;\n    } else {\n      features.position = cluster_position::right;\n      features.symmetric_x1 = abs(temp1);\n      features.symmetric_x2 = abs(temp2);\n    }\n  }\n\n  return features;\n}\n\nauto w_ocr_engine::check_twin_clusters(_In_ cluster_features &pFirstInput,\n                                       _In_ cluster_features &pSecondInput,\n                                       _In_ float pThreshold) -> bool {\n  bool result = false;\n\n  float Y_diff_ration =\n      float(std::abs(pFirstInput.average_y - pSecondInput.average_y)) /\n      float((pFirstInput.average_height + pSecondInput.average_height) / 2);\n  float a, b, overlapped_ratio;\n\n  float height_diff_ratio =\n      (pFirstInput.average_height > pSecondInput.average_height)\n          ? float(pFirstInput.average_height - pSecondInput.average_height) /\n                float(pFirstInput.average_height)\n          : float(pSecondInput.average_height - pFirstInput.average_height) /\n                float(pSecondInput.average_height);\n\n  if (Y_diff_ration < 0.05 && height_diff_ratio < 0.05) {\n    a = (pFirstInput.symmetric_x1 < pSecondInput.symmetric_x1)\n            ? float(pSecondInput.symmetric_x1)\n            : float(pFirstInput.symmetric_x1);\n    b = (pFirstInput.symmetric_x2 < pSecondInput.symmetric_x2)\n            ? float(pFirstInput.symmetric_x2)\n            : float(pSecondInput.symmetric_x2);\n\n    overlapped_ratio =\n        (b - a) / float(pFirstInput.symmetric_x2 - pFirstInput.symmetric_x1);\n    float temp =\n        (b - a) / float(pSecondInput.symmetric_x2 - pSecondInput.symmetric_x1);\n\n    overlapped_ratio = (overlapped_ratio > temp) ? overlapped_ratio : temp;\n\n    if (overlapped_ratio > pThreshold) {\n      result = true;\n    }\n  }\n\n  return result;\n}\n\nauto w_ocr_engine::keep_twins(\n    _Inout_ std::vector<std::vector<characters_struct>> &pClusteredChar,\n    _In_ int pImageWidth, _In_ int pImageHeight, _In_ bool pWord) -> void {\n  std::vector<cluster_features> cluster_features_vector;\n  int n_cluster = pClusteredChar.size();\n\n  for (int i = 0; i < n_cluster; i++) {\n    cluster_features_vector.push_back(\n        fill_cluster_features(pClusteredChar[i], pImageWidth, i));\n  }\n\n  for (int i = 0; i < n_cluster - 1; i++) {\n    if (cluster_features_vector[i].matched) {\n      continue;\n    }\n    for (int j = i + 1; j < n_cluster; j++) {\n      if (cluster_features_vector[j].matched) {\n        continue;\n      }\n      if (check_twin_clusters(cluster_features_vector[i],\n                              cluster_features_vector[j], 0.6)) {\n        cluster_features_vector[i].matched = true;\n        cluster_features_vector[j].matched = true;\n\n        cluster_features_vector[i].twin_index_in_parent_vector =\n            cluster_features_vector[j].index_in_parent_vector;\n        cluster_features_vector[j].twin_index_in_parent_vector =\n            cluster_features_vector[i].index_in_parent_vector;\n      }\n    }\n  }\n\n  if (pWord) {\n    for (int i = 1; i < n_cluster; i++) {\n      if (!cluster_features_vector[i].matched) {\n        continue;\n      }\n\n      if (cluster_features_vector[i].average_y > pImageHeight * 4 / 5) {\n        cluster_features_vector[i].matched = false;\n        cluster_features_vector[cluster_features_vector[i]\n                                    .twin_index_in_parent_vector]\n            .matched = false;\n      }\n    }\n\n    int more = -1;\n\n    for (int i = 1; i < n_cluster; i++) {\n      if (!cluster_features_vector[i].matched) {\n        continue;\n      }\n      if (more == -1) {\n        more = pClusteredChar[i].size();\n      }\n\n      if (more < pClusteredChar[i].size()) {\n        more = pClusteredChar[i].size();\n      }\n    }\n\n    for (int i = 1; i < n_cluster; i++) {\n      if (!cluster_features_vector[i].matched) {\n        continue;\n      }\n\n      if (more > pClusteredChar[i].size() &&\n          more > pClusteredChar[cluster_features_vector[i]\n                                    .twin_index_in_parent_vector]\n                     .size()) {\n        cluster_features_vector[i].matched = false;\n        cluster_features_vector[cluster_features_vector[i]\n                                    .twin_index_in_parent_vector]\n            .matched = false;\n      }\n    }\n  } else {\n    int largest = -1;\n\n    for (int i = 1; i < n_cluster; i++) {\n      if (!cluster_features_vector[i].matched) {\n        continue;\n      }\n      if (largest == -1) {\n        largest = cluster_features_vector[i].average_height;\n      }\n\n      if (largest < cluster_features_vector[i].average_height) {\n        largest = cluster_features_vector[i].average_height;\n      }\n    }\n\n    for (int i = 1; i < n_cluster; i++) {\n      if (!cluster_features_vector[i].matched) {\n        continue;\n      }\n      if (largest == -1) {\n        largest = cluster_features_vector[i].average_height;\n      }\n\n      if (largest > cluster_features_vector[i].average_height &&\n          largest > cluster_features_vector[cluster_features_vector[i]\n                                                .twin_index_in_parent_vector]\n                        .average_height) {\n        cluster_features_vector[i].matched = false;\n        cluster_features_vector[cluster_features_vector[i]\n                                    .twin_index_in_parent_vector]\n            .matched = false;\n      } else {\n        largest = cluster_features_vector[i].average_height;\n      }\n    }\n  }\n\n  for (int i = 0; i < n_cluster; i++) {\n    int index = n_cluster - (i + 1);\n    if (!cluster_features_vector[index].matched) {\n      pClusteredChar.erase(pClusteredChar.begin() + index);\n    }\n  }\n\n  return;\n}\n\nauto w_ocr_engine::keep_time(\n    _Inout_ std::vector<std::vector<characters_struct>> &pClusteredChar)\n    -> void {\n  int n_cluster = pClusteredChar.size();\n  if (n_cluster == 0) {\n    return;\n  }\n  int height = pClusteredChar[n_cluster - 1][0].bound_rect.y;\n\n  for (int i = 1; i < n_cluster; i++) {\n    int index = n_cluster - (i + 1);\n    if (height < pClusteredChar[index][0].bound_rect.y) {\n      pClusteredChar.erase(pClusteredChar.begin() + index);\n    } else {\n      height = pClusteredChar[index][0].bound_rect.y;\n      pClusteredChar.pop_back();\n    }\n  }\n}\n\nauto w_ocr_engine::add_text_to_original_image(\n    _Inout_ cv::Mat &pImage,\n    _In_ std::vector<characters_struct> &pClusteredChar) -> void {\n  for (int i = 0; i < pClusteredChar.size(); i++) {\n    cv::putText(pImage, pClusteredChar[i].text,\n                cv::Point(pClusteredChar[i].bound_rect.x,\n                          pClusteredChar[i].bound_rect.y + 100),\n                cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 255, 0), false);\n  }\n\n  return;\n}\n"
  },
  {
    "path": "wolf/ml/referee_ocr/w_ocr_engine.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <tesseract/baseapi.h>\n\n#include <algorithm>\n#include <cmath>\n#include <iostream>\n#include <opencv2/opencv.hpp>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"w_image_processor.hpp\"\n\nnamespace wolf::ml::ocr {\n\n//! optical character reader class.\n/*! \\brief This class is responsible for manipulating the OCR tasks.\n\n        This class contains functions, structures, and variables that use\n   for optical character reading purposes. In the project, in other classes,\n   in the case of reading an optical character, one must create an object of\n   the OCR class.\n*/\nclass w_ocr_engine {\npublic:\n  //! The enum shows the position of the cluster in the whole image.\n  enum cluster_position { left, right, middle };\n  //! The struct contains the features related to a cluster.\n  struct cluster_features {\n    /*!<The minimum amount of x value on the x-axis between all characters in\n     * the cluster.*/\n    int min_x;\n    /*!<The maximum amount of x value on the x-axis between all characters in\n     * the cluster.*/\n    int max_x;\n    /*!<The minimum amount of y value on the y-axis between all characters in\n     * the cluster.*/\n    int min_y;\n    /*!<The average amount of y value of all characters.*/\n    int average_y;\n    /*!<The average height of all characters in pixel.*/\n    int average_height;\n    /*!<The distance between min_x and the middle of the frame.*/\n    int symmetric_x1;\n    /*!<The distance between max_x and the middle of the frame.*/\n    int symmetric_x2;\n    /*!<The position of the cluster in the frame.*/\n    cluster_position position;\n    /*!<The index of the current array in the parent vector.*/\n    int index_in_parent_vector;\n    /*!<The index of the twin array in the parent vector.*/\n    int twin_index_in_parent_vector;\n\n    /*!<If the cluster has a twin this variable should set true.*/\n    bool matched = false;\n  };\n  //! Struct of the character information.\n  struct characters_struct {\n    /*!<Change to true after processing the character.*/\n    bool processed = false;\n    /*!<This variable shows the height of the character in pixel.*/\n    int height;\n    /*!<This variable contains the coordination of the character.*/\n    cv::Point center;\n    /*!<Show the character bounding box corners.*/\n    cv::Rect bound_rect;\n    /*!<The character text.*/\n    std::string text;\n    /*!<The character contour area.*/\n    std::vector<cv::Point> contour;\n    /*!<The operator is added to the struct to make it sortable.*/\n    bool operator<(const characters_struct &rhs) const {\n      return center.x < rhs.center.x;\n    }\n  };\n  //! Struct of the character information.\n  struct result_boxes {\n    bool got_result = false;\n\n    characters_struct home_name;\n    characters_struct away_name;\n    characters_struct home_result;\n    characters_struct away_result;\n  };\n  //! Struct of the character value and position.\n  struct character_and_center {\n    std::string text = \"\";\n    cv::Point center;\n    /*!<The operator is added to the struct to make it sortable.*/\n    bool operator<(const character_and_center &rhs) const {\n      return center.x < rhs.center.x;\n    }\n  };\n  // config_for_ocr_struct config_for_ocr_struct2;\n\n  //! All configurations need for w_ocr_engine.\n  /*!\n          The necessary configurations use for creating w_ocr_engine class\n     objects.\n  */\n  struct config_struct {\n    /*!<Set a name for each window area.*/\n    std::string name;\n    /*!<If is time then true.*/\n    bool is_time = false;\n    bool relative = false;\n    bool is_result = false;\n    /*!<Show if the area has been checked.*/\n    bool if_checked = false;\n    /*!<Show the window corners.*/\n    cv::Rect window;\n    float fraction = 1.0;\n    /*!<OCR configuration struct.*/\n    config_for_ocr_struct config_for_ocr;\n  };\n\n  //! Result struct.\n  struct result {\n    int home_result;\n    int away_result;\n    std::string home_name;\n    std::string away_name;\n  };\n\n  /*!\n          The constructor of the class.\n\n          Tesseract objects are initialized in the constructor.\n  */\n  w_ocr_engine();\n  /*!\n          The deconstructor of the class.\n\n          Tesseract objects are ended in the deconstructor.\n  */\n  ~w_ocr_engine();\n\n  /*!\n          The char_vec_to_string function converts the input vector to the\n     related strings.\n\n          \\param  frame    The image needs to be processed.\n          \\param  frame_number    The current image is the nth image of the\n     video. frame_number contains the value of n. \\param  ocr_config    The\n     necessary configurations for processing optical characters. \\return returns\n     the text of the game scene\n  */\n  auto char_vec_to_string(\n      _In_ std::vector<w_ocr_engine::characters_struct> char_vector,\n      _In_ cv::Mat &frame, _In_ config_for_ocr_struct &ocr_config)\n      -> std::vector<character_and_center>;\n\n  /*!\n          The image_to_string function gets an image and returns the text of the\n     box.\n\n          \\param  frame_box    The image needs to be processed.\n          \\param  ocr_config    The necessary configurations for processing\n     optical characters. \\return    returns the text of frame_box\n  */\n  std::vector<character_and_center>\n  image_to_string(_In_ cv::Mat &frame_box,\n                  _In_ config_for_ocr_struct &ocr_config);\n\n  /*!\n          The check_if_overlapped checks the input rect of boxes to decide if\n     two rects overlapped.\n\n          \\param  box_1    The rect information of the first box.\n          \\param  box_2    The rect information of the second box.\n          \\param  ocr_config    The necessary configurations for processing\n     optical characters. \\return    True, if two boxes overlapped.\n  */\n  bool check_if_overlapped(_In_ cv::Rect box_1, _In_ cv::Rect box_2,\n                           _In_ config_for_ocr_struct &ocr_config);\n\n  /*!\n          Get vector of contours and create a vector of char structs. this\n     structs does not have text.\n\n          \\param  contours    a vector contains contours.\n          \\return    a vector contains character structs\n  */\n  std::vector<w_ocr_engine::characters_struct>\n  contours_to_char_structs(_In_ std::vector<std::vector<cv::Point>> contours);\n\n  /*!\n          The enchance_contour_image function modifies the background of the\n     contour, makes the background white. The function also resizes the contour\n     image to reach a better w_ocr_engine result.\n\n          \\param  contour_image    The modified contour image. The output image\n     of the function. \\param  ocr_config    The necessary configurations for\n     processing optical characters.\n  */\n  void enhance_contour_image_for_model(_Inout_ cv::Mat &contour_image,\n                                       _In_ config_for_ocr_struct &ocr_config);\n\n  /*!\n          The euclidean_distance function calculates the euclidean distance of\n     two input characters.\n\n          \\param  first_character    The first character.\n          \\param  second_character    The second character.\n          \\return    The calculated distance of two input characters.\n  */\n  double euclidean_distance(characters_struct &first_character,\n                            characters_struct &second_character);\n\n  auto euclidean_distance(int x1, int x2, int y1, int y2) -> double;\n\n  /*!\n          The spaces_between_two_chars function returns a string containing the\n     spaces that should be placed between characters.\n\n          \\param  left_char    The left hand side character.\n          \\param  right_char   The right hand side character.\n          \\param  height_to_dist_ratio The ratio of the character height and\n     distance. \\return    The spaces that should be placed between characters.\n  */\n  auto spaces_between_two_chars(_In_ characters_struct left_char,\n                                _In_ characters_struct right_char,\n                                _In_ float height_to_dist_ratio) -> std::string;\n\n  /*!\n          The char_clusters_to_text puts the clustered characters together to\n     create the word. This function uses one of the class variables as input and\n     stores the result in another variable of the class.\n  */\n  std::vector<character_and_center> char_clusters_to_text(\n      _In_ std::vector<std::vector<characters_struct>> clustered_characters);\n\n  /*!\n          The filter_chars_by_contour_size function eliminates abnormal contours\n     from the char struct vector and returns new vector.\n\n          \\param  contours    A vector of all contours.\n          \\param  ocr_config   The necessary configurations for processing\n     optical characters. \\return    a vector of char structs.\n  */\n  std::vector<characters_struct>\n  filter_chars_by_contour_size(_In_ std::vector<characters_struct> &character,\n                               _In_ config_for_ocr_struct &ocr_config);\n\n  /*!\n          the image_to_char_structs takes an image and returns a vector of char\n     struct.\n\n          \\param  frame_box    image contains characters.\n          \\param  ocr_config   The necessary configurations for processing\n     optical characters. \\return    a vector of char structs.\n  */\n  std::vector<characters_struct>\n  image_to_char_structs(_In_ cv::Mat &frame_box,\n                        _In_ config_for_ocr_struct &ocr_config);\n\n  /*!\n          Takes vector of char structs and recognize text in each struct.\n\n          \\param  characters    vector of char structs\n          \\param  frame_box    image contains characters.\n          \\param  ocr_config   The necessary configurations for processing\n     optical characters. \\return    a vector of char structs.\n  */\n  std::vector<characters_struct>\n  label_chars_in_char_structs(_In_ std::vector<characters_struct> &characters,\n                              _In_ cv::Mat &frame_box,\n                              _In_ config_for_ocr_struct &ocr_config);\n\n  /*!\n          The margin_bounding_rect function margins the contours. It is\n     necessary for obtaining better results.\n\n          \\param  bounding_rect    A vector of the bounding rect of the\n     contours. \\param  margin    The margin value. \\param  filtered_image image\n     contains characters.\n\n  */\n  void margin_bounding_rect(_Inout_ cv::Rect &bounding_rect, _In_ int margin,\n                            _In_ cv::Mat &filtered_image);\n\n  /*!\n          The mask_contour function applies the mask of the contour area to the\n     input image. The resulting image should contain the contour.\n\n          \\param  image    The input image. A window of the original image. The\n     window contains all characters of one property. \\param  contour_info\n     Information of the desired contour. \\return  The modified contour image.\n     The output image of the function.\n  */\n  cv::Mat mask_contour(_In_ cv::Mat &image,\n                       _In_ characters_struct &contour_info);\n\n  /*!\n          The merge_overlapped_contours function merges the overlapped contours.\n\n          \\param  bound_rect    A vector of the bounding rect of the contours.\n          \\param  ocr_config    The necessary configurations for processing\n     optical characters.\n  */\n  void\n  merge_overlapped_contours(_Inout_ std::vector<characters_struct> &bound_rect,\n                            _In_ config_for_ocr_struct &ocr_config);\n\n  /*!\n          The cluster_char_structs function puts related characters togethter.\n\n          \\param  ocr_config    The necessary configurations for processing\n     optical characters.\n  */\n  std::vector<std::vector<characters_struct>>\n  cluster_char_structs(std::vector<w_ocr_engine::characters_struct> characters,\n                       config_for_ocr_struct &ocr_config);\n\n  /*!\n          The function resizes the input image and maps it in the output image.\n     It helps the programmers to check their algorithm's influence on the input\n     image in a better way.\n\n          \\param  input_image    The input image.\n          \\param  out_put_image_height    The height of output image.\n          \\param  resize_factor    The resize factor.\n          \\return    returns resized image\n  */\n  cv::Mat show_in_better_way(cv::Mat &input_image,\n                             int out_put_image_height = 400,\n                             float resize_factor = 5);\n\n  /*!\n          The split_string function uses for splitting input strings based on\n     the reference character.\n\n          \\param  input_string    The input string.\n          \\param  reference    The strings that are located between two\n     references would be placed in a string. \\return    A vector of split\n     string.\n  */\n  std::vector<std::string> split_string(std::string input_string,\n                                        char reference);\n\n  /*!\n          The same_height function returns true if all characters in the cluster\n     share the same height.\n\n          \\param  pClusteredChars    The cluster contains many characters.\n          \\return    The result would be true if all characters in the cluster\n     share the same height.\n  */\n  auto same_height(_In_ std::vector<characters_struct> pClusteredChars) -> bool;\n\n  /*!\n          The same_level function returns true if all characters in the cluster\n     share the same y-position.\n\n          \\param  pClusteredChars    The cluster contains many characters.\n          \\return    The result would be true if all characters in the cluster\n     share the same y-position.\n  */\n  auto same_level(_In_ std::vector<characters_struct> pClusteredChars) -> bool;\n\n  /*!\n          The same_level function returns true if all characters in the cluster\n     share the same y-position.\n\n          \\param  image    A frame of the game.\n          \\param  pClusteredChars    The cluster contains many characters.\n          \\param  pWindowName    The cv::imshow image name.\n          \\param  pShow\n          \\return    The output would be a cv image containing the clusters.\n  */\n  static auto show_contours(_Inout_ cv::Mat &pImage,\n                            _In_ std::vector<characters_struct> pClusteredChars,\n                            _In_ std::string pWindowName,\n                            _In_ bool pShow = true) -> void;\n\n  /*!\n          The fill_cluster_features function extracts all feature of the input\n     cluster.\n\n          \\param  pClusteredChars    The cluster contains many characters.\n          \\param  pImageWidth    The width of input image in pixel.\n          \\param  pIndex    The index of the array in the vector.\n          \\return    An structure of the cluster features.\n  */\n  auto\n  fill_cluster_features(_Inout_ std::vector<characters_struct> &pClusteredChar,\n                        _In_ int pImageWidth, _In_ int pIndex)\n      -> cluster_features;\n\n  /*!\n          The check_twin_clusters function checks the input cluster features and\n     decides whether two input clusters are twins.\n\n          \\param  pFirstInput    The first cluster features.\n          \\param  pSecondInput    The second cluster features.\n          \\param  pThreshold    The threshold for decision-making.\n          \\return    The result would be true if the input clusters are twins.\n  */\n  auto check_twin_clusters(_In_ cluster_features &pFirstInput,\n                           _In_ cluster_features &pSecondInput,\n                           _In_ float pThreshold) -> bool;\n\n  /*!\n          The keep_twins function eliminates the single clusters.\n\n          \\param  pClusteredChars    The cluster contains many characters.\n          \\param  pImageWidth    The width of input image in pixel.\n          \\param\tpWord    The value would be \"true\" if it is a word\n     cluster. \\return\n  */\n  auto keep_twins(\n      _Inout_ std::vector<std::vector<characters_struct>> &pClusteredChar,\n      _In_ int pImageWidth, _In_ int pImageHeight, _In_ bool pWord) -> void;\n\n  /*!\n          The keep_time function keeps the time cluster.\n\n          \\param  pClusteredChars    The cluster contains many characters.\n          \\return\n  */\n  auto\n  keep_time(_Inout_ std::vector<std::vector<characters_struct>> &pClusteredChar)\n      -> void;\n\n  /*!\n          The add_text_to_original_image adds texts to the input image.\n\n          \\param  pImage    The input image.\n          \\param  pClusteredChars    The cluster contains many characters.\n          \\return\n  */\n  auto add_text_to_original_image(\n      _Inout_ cv::Mat &pImage,\n      _In_ std::vector<characters_struct> &pClusteredChar) -> void;\n\nprivate:\n  /*!<An object of tesseract library (to recognize digits)..*/\n  tesseract::TessBaseAPI *digit_api = new tesseract::TessBaseAPI();\n  /*!<An object of tesseract library (to recognize words).*/\n  tesseract::TessBaseAPI *word_api = new tesseract::TessBaseAPI();\n};\n} // namespace wolf::ml::ocr\n"
  },
  {
    "path": "wolf/ml/referee_ocr/w_read_video_frames.cpp",
    "content": "#include \"w_read_video_frames.hpp\"\n#ifdef __TELEMETRY\n#include \"opentelemetry/logs/provider.h\"\n#include \"opentelemetry/sdk/version/version.h\"\n#include \"opentelemetry/trace/provider.h\"\n\nnamespace trace = opentelemetry::trace;\nnamespace nostd = opentelemetry::nostd;\n\nnamespace {\nnostd::shared_ptr<trace::Tracer> get_tracer() {\n  auto provider = trace::Provider::GetTracerProvider();\n  return provider->GetTracer(\"pes_21\", OPENTELEMETRY_SDK_VERSION);\n}\n\n} // namespace\n#endif\n\nusing w_read_video_frames = wolf::ml::ocr::w_read_video_frames;\n\nw_read_video_frames::w_read_video_frames(std::string video_path) {\n  path = video_path;\n\n  cap = cv::VideoCapture(path.c_str(), cv::CAP_ANY);\n  if (!cap.isOpened()) {\n    std::cout << \"Error opening video stream or file\" << std::endl;\n  }\n  frame_count = cap.get(cv::CAP_PROP_FRAME_COUNT);\n}\n\ncv::Mat w_read_video_frames::read_video_frame_by_frame() {\n  cv::Mat frame;\n  if (!cap.read(frame)) {\n    release();\n    return frame;\n  }\n  frame_number += 1;\n  return frame;\n}\n\nvoid w_read_video_frames::write_image_to_video(std::string out_video_path) {\n#ifdef __TELEMETRY\n  auto scoped_span =\n      trace::Scope(get_tracer()->StartSpan(\"write_image_to_video\"));\n#endif\n  cv::Mat frame;\n\n  frame = read_video_frame_by_frame();\n  if (frame.empty()) {\n    std::cout << \"Error opening video stream\" << std::endl;\n    return;\n  }\n  int frame_width = frame.cols;\n  int frame_height = frame.rows;\n\n  // Define the codec and create VideoWriter object.The output is stored in\n  // 'outcpp.avi' file.\n  cv::VideoWriter video(out_video_path,\n                        cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 60.0,\n                        cv::Size(frame_width, frame_height));\n\n  while (true) {\n    frame = read_video_frame_by_frame();\n    if (frame.empty())\n      break;\n\n    // Write the frame into the file 'outcpp.avi'\n    video.write(frame);\n    cv::waitKey(10);\n  }\n\n  video.release();\n  frame.release();\n\n  return;\n}\n\nvoid w_read_video_frames::release() { cap.release(); }\n\ncv::Mat w_read_video_frames::read_specific_frame(int input_frame_number) {\n  frame_number = input_frame_number;\n\n  cv::Mat frame;\n  if (frame_number > int(frame_count)) {\n    release();\n    return frame;\n  }\n  cap.set(1, frame_number);\n\n  if (!cap.read(frame)) {\n    return frame;\n  }\n\n  return frame;\n}\n\nint w_read_video_frames::get_current_frame_number() { return frame_number; }\n\ndouble w_read_video_frames::get_frame_amount() { return frame_count; }\n\nvoid w_read_video_frames::video_player() {\n  w_read_video_frames player(path);\n\n  int skip = 100;\n  int frame_number = 52000 - skip;\n\n  while (true) {\n    frame_number += skip;\n\n    cv::Mat frame = player.read_specific_frame(frame_number);\n    cv::imshow(\"video player\", frame);\n    std::cout << frame_number << std::endl;\n    int key = cv::waitKey();\n    //        std::cout << key << std::endl;\n\n    if (key == 1113937 || key == 1113940) {\n      frame_number -= 2 * skip;\n    }\n  }\n}\n"
  },
  {
    "path": "wolf/ml/referee_ocr/w_read_video_frames.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <iostream>\n#include <opencv2/opencv.hpp>\n\n#include \"wolf.hpp\"\n\nnamespace wolf::ml::ocr {\n\n//! read frames of the video class.\n/*! \\brief This class is responsible for reading the frame of the input\n   video.\n\n        This class contains functions, structures, and variables that use\n   for reading the frames of the input video.\n*/\nclass w_read_video_frames {\npublic:\n  /*!<The path of the video.*/\n  std::string path;\n  /*!<Video Capture APIs.*/\n  cv::VideoCapture cap;\n  /*!<The frame number in the video frames.*/\n  int frame_number = 0;\n  /*!<Number of frames of the video.*/\n  double frame_count;\n\n  /*!\n  The constructor of the class.\n\n  \\param  video_path    The path of video.\n  */\n  W_API w_read_video_frames(std::string video_path);\n\n  /*!\n  The read_video_frame_by_frame function extracts frames of the input video one\n  by one in order.\n\n  \\return    The next frame of video\n  */\n  W_API cv::Mat read_video_frame_by_frame();\n  /*!\n  The write_image_to_video function puts related images next to each other for\n  creating a video.\n\n  \\param  out_video_path    The path of output video.\n*/\n  W_API void write_image_to_video(std::string out_video_path);\n  /*!\n  The read_specific_frame function reads a specific frame of the video.\n\n  \\param  input_frame_number     Frame number of desired frame in the video\n  frames. \\return    Specific frame of the video\n*/\n  W_API cv::Mat read_specific_frame(int input_frame_number);\n  /*!\n  The get_current_frame_number function returns the current frame number.\n\n  \\return    Current frame number.\n*/\n  W_API int get_current_frame_number();\n  /*!\n  The get_frame_amount function returns the number of frames of the video.\n\n  \\return    Number of frames of the video.\n*/\n  W_API double get_frame_amount();\n  /*!\n  The video_player function implements a simple video player based on OpenCV.\n*/\n  [[noreturn]] void video_player();\n  /*!\n  The release function call cv::VideoCapture::release() function.\n*/\n  void release();\n}; // namespace wolf::ml::ocr\n} // namespace wolf::ml::ocr"
  },
  {
    "path": "wolf/ml/referee_ocr/w_referee.cpp",
    "content": "#include \"w_referee.hpp\"\n\n#include <chrono>\n#include <opencv2/opencv.hpp>\n\nusing w_referee = wolf::ml::ocr::w_referee;\nusing w_ocr_engine = wolf::ml::ocr::w_ocr_engine;\n\nw_referee::w_referee() {}\n\nvoid w_referee::match_result_struct::release() {\n  match_result_struct::result_image.release();\n}\n\nw_ocr_engine::character_and_center w_referee::concatenate_name_result(\n    std::vector<w_ocr_engine::character_and_center> &result) {\n  w_ocr_engine::character_and_center temp_concatenated_result = result[0];\n\n  for (size_t i = 1; i < result.size(); i++) {\n    temp_concatenated_result.text =\n        temp_concatenated_result.text + \" \" + result[i].text;\n  }\n\n  return temp_concatenated_result;\n}\n\nauto w_referee::if_the_string_is_in_the_vector(\n    w_ocr_engine::character_and_center the_character,\n    std::vector<vote_over_string_vector> &the_vector) -> bool {\n  bool is_in_the_vector = false;\n\n  for (size_t i = 0; i < the_vector.size(); i++) {\n    // std::cout << the_string.c_str() << \" : \" << the_vector[i].str.c_str() <<\n    // \"  \" << std::strcmp(the_string.c_str(), the_vector[i].str.c_str()) <<\n    // std::endl;\n    if (std::strcmp(the_character.text.c_str(), the_vector[i].str.c_str()) ==\n        0) {\n      is_in_the_vector = true;\n      the_vector[i].already_voted++;\n      break;\n    }\n  }\n\n  if (!is_in_the_vector) {\n    vote_over_string_vector temp;\n    temp.str = the_character.text;\n    temp.center = the_character.center;\n    the_vector.push_back(temp);\n  }\n\n  return is_in_the_vector;\n}\n\nauto w_referee::voting_over_results_and_names(\n    frame_result_struct &voted_results,\n    std::vector<frame_result_struct> &all_results) -> void {\n  std::vector<vote_over_string_vector> home_result{};\n  std::vector<vote_over_string_vector> away_result{};\n  std::vector<vote_over_string_vector> home_name{};\n  std::vector<vote_over_string_vector> away_name{};\n  std::vector<vote_over_string_vector> home_penalty_result{};\n  std::vector<vote_over_string_vector> away_penalty_result{};\n\n  home_result.clear();\n  away_result.clear();\n  home_name.clear();\n  away_name.clear();\n\n  for (int j = 0; j < all_results.size(); j++) {\n    if_the_string_is_in_the_vector(all_results[size_t(j)].home_result,\n                                   home_result);\n    if_the_string_is_in_the_vector(all_results[size_t(j)].away_result,\n                                   away_result);\n    if_the_string_is_in_the_vector(all_results[size_t(j)].home_name, home_name);\n    if_the_string_is_in_the_vector(all_results[size_t(j)].away_name, away_name);\n    if (all_results[size_t(j)].home_penalty_result.text.compare(\"\") != 0) {\n      if_the_string_is_in_the_vector(all_results[size_t(j)].home_penalty_result,\n                                     home_penalty_result);\n    }\n    if (all_results[size_t(j)].away_penalty_result.text.compare(\"\") != 0) {\n      if_the_string_is_in_the_vector(all_results[size_t(j)].away_penalty_result,\n                                     away_penalty_result);\n    }\n  }\n\n  std::sort(home_result.begin(), home_result.end());\n  std::sort(away_result.begin(), away_result.end());\n  std::sort(home_name.begin(), home_name.end());\n  std::sort(away_name.begin(), away_name.end());\n  if (home_penalty_result.size() != 0 && away_penalty_result.size() != 0) {\n    std::sort(home_penalty_result.begin(), home_penalty_result.end());\n    std::sort(away_penalty_result.begin(), away_penalty_result.end());\n    voted_results.home_penalty_result.text =\n        home_penalty_result[home_penalty_result.size() - 1].str;\n    voted_results.home_penalty_result.center =\n        home_penalty_result[home_penalty_result.size() - 1].center;\n    voted_results.away_penalty_result.text =\n        away_penalty_result[away_penalty_result.size() - 1].str;\n    voted_results.away_penalty_result.center =\n        away_penalty_result[away_penalty_result.size() - 1].center;\n  }\n  voted_results.home_result.text = home_result[home_result.size() - 1].str;\n  voted_results.home_result.center = home_result[home_result.size() - 1].center;\n  voted_results.away_result.text = away_result[away_result.size() - 1].str;\n  voted_results.away_result.center = away_result[away_result.size() - 1].center;\n  voted_results.home_name.text = home_name[home_name.size() - 1].str;\n  voted_results.home_name.center = home_name[home_name.size() - 1].center;\n  voted_results.away_name.text = away_name[away_name.size() - 1].str;\n  voted_results.away_name.center = away_name[away_name.size() - 1].center;\n\n  voted_results.frame_number = all_results[0].frame_number;\n  voted_results.stat = all_results[0].stat;\n\n  return;\n}\n"
  },
  {
    "path": "wolf/ml/referee_ocr/w_referee.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <iostream>\n#include <opencv2/opencv.hpp>\n\n#include \"w_ocr_engine.hpp\"\n#include \"w_read_video_frames.hpp\"\n#include \"wolf.hpp\"\n\nnamespace wolf::ml::ocr {\n\n//! w_referee class.\n/*! \\brief This class is a bridge between the w_ocr_engine class and the referee\n   task.\n\n        This class contains functions, structures, and variables that use the\n   w_ocr_engine class for doing referee purposes.\n*/\nclass w_referee {\npublic:\n  //! The result_type enum shows the state of the result.\n  /*!\n          The result of the game would be stored in the database based on this\n     enum and each stat has own properties.\n  */\n  enum result_type {\n    first_half,\n    second_half,\n    extra_first_half,\n    extra_second_half,\n    penalty,\n    final_result\n  };\n\n  //! A structure for the frame result.\n  /*!\n    The structure will be filled after the end of each frame processing and\n    contain the frame necessary results.\n  */\n  struct frame_result_struct {\n    /*!<The home team scores(left).*/\n    w_ocr_engine::character_and_center home_result;\n    /*!<The away team scores.*/\n    w_ocr_engine::character_and_center away_result;\n    /*!<The home team name.*/\n    w_ocr_engine::character_and_center home_name;\n    /*!<The away team name.*/\n    w_ocr_engine::character_and_center away_name;\n    /*!<The home team penalty scores(left).*/\n    w_ocr_engine::character_and_center home_penalty_result;\n    /*!<The away team penalty scores.*/\n    w_ocr_engine::character_and_center away_penalty_result;\n    /*!<The frame number of the result image.*/\n    int frame_number;\n    /*!<The stat of the game.*/\n    std::string stat;\n    /*!<The operator is added to the struct to make it sortable.*/\n    bool operator<(const frame_result_struct &rhs) const {\n      return frame_number < rhs.frame_number;\n    }\n  };\n\n  //! A structure for the match result.\n  /*!\n    The structure will be filled after the end of each game processing and\n    contain the match necessary results.\n  */\n  struct match_result_struct {\n    /*!<The results of frames share the same stat.*/\n    std::vector<frame_result_struct> all_frames_results;\n    /*!<The home team scores(left).*/\n    w_ocr_engine::character_and_center home_result;\n    /*!<The away team scores.*/\n    w_ocr_engine::character_and_center away_result;\n    /*!<The home team name.*/\n    w_ocr_engine::character_and_center home_name;\n    /*!<The away team name.*/\n    w_ocr_engine::character_and_center away_name;\n    /*!<The home team penalty scores(left).*/\n    w_ocr_engine::character_and_center home_penalty_result;\n    /*!<The away team penalty scores.*/\n    w_ocr_engine::character_and_center away_penalty_result;\n\n    /*!<The frame number.*/\n    int frame_number;\n    /*!<The stat of the game.*/\n    std::string stat;\n    /*!<This image is related to the extracted result.*/\n    cv::Mat result_image;\n\n    /*!<The ready variable shows the match result is ready.*/\n    bool ready = false;\n    /*!<The ready variable shows the match result is extracted..*/\n    bool extracted = false;\n    /*!<The ready variable shows the match result is applied.*/\n    bool applied = false;\n\n  public:\n    /*!\n      Release the memory.\n\n      This function frees the allocated memory.\n    */\n    void release();\n  };\n\n  /*!\n          The constructor of the class.\n\n          The function is empty.\n    */\n  W_API w_referee();\n\npublic:\n  //! Contain the text and its repetition in the results.\n  /*!\n    The final result is extracted from a series of results. This struct contains\n    its vote throw the process.\n  */\n  struct vote_over_string_vector {\n    /*!<The candidate text.*/\n    std::string str;\n    /*!<The center coordination of the characters.*/\n    cv::Point center;\n    /*!<The text vote number.*/\n    int already_voted = 1;\n    /*!<The operator is added to the struct to make it sortable.*/\n    bool operator<(const vote_over_string_vector &rhs) const {\n      return already_voted < rhs.already_voted;\n    }\n  };\n\n  //! Start and End of each match.\n  /*!\n    The input video may contain multiple matches. It is a way to track the start\n    and end frame of each game.\n  */\n  struct related_results {\n    /*!<The frame number of the first image of the game.*/\n    int start;\n    /*!<The frame number of the last image of the game.*/\n    int end;\n    /*!<The operator is added to the struct to make it sortable.*/\n    bool operator<(const related_results &rhs) const {\n      return start < rhs.start;\n    }\n  };\n  /*!<This config helps to avoid processing of the frames which does not contain\n   * the game result.*/\n  w_ocr_engine::config_struct if_extract_game_result;\n  /*!<The config for part of the image contains the score of the home team.*/\n  w_ocr_engine::config_struct extract_game_result_home;\n  /*!<The config for part of the image contains the name of the home team.*/\n  w_ocr_engine::config_struct extract_home_name;\n  /*!<The config for part of the image contains the score of the away team.*/\n  w_ocr_engine::config_struct extract_game_result_away;\n  /*!<The config for part of the image contains the name of the away team.*/\n  w_ocr_engine::config_struct extract_away_name;\n  /*!\n          The function concatenates the separated alphabet of the team name.\n\n          \\param result A vector of alphabets.\n          \\return return the whole word of the team name.\n  */\n  w_ocr_engine::character_and_center concatenate_name_result(\n      std::vector<w_ocr_engine::character_and_center> &result);\n\n  /*!\n          The function updates the vector of voting.\n\n          First, it checks if the input string is in the vector. If true, then\n     the voting value would be incremented. Otherwise, a new variable would be\n     added to the vector.\n\n          \\param the_character the input string and the related information\n     related to the string. \\param the_vector vector of string with theirs\n     repetition number. \\return is the string in the vector?\n  */\n  W_API auto if_the_string_is_in_the_vector(\n      w_ocr_engine::character_and_center the_character,\n      std::vector<vote_over_string_vector> &the_vector) -> bool;\n\n  /*!\n          The voting function.\n\n          \\param voted_results The voted results.\n          \\param all_results All results.\n  */\n  W_API void\n  voting_over_results_and_names(frame_result_struct &voted_results,\n                                std::vector<frame_result_struct> &all_results);\n};\n} // namespace wolf::ml::ocr"
  },
  {
    "path": "wolf/ml/referee_ocr/w_soccer.cpp",
    "content": "#include \"w_soccer.hpp\"\n\n#include <chrono>\n#include <cstdint>\n#include <filesystem>\n#include <fstream>\n#include <opencv2/opencv.hpp>\n#include <string>\n\n#include \"w_referee.hpp\"\n#include \"w_utilities.hpp\"\n\nusing w_soccer = wolf::ml::ocr::w_soccer;\nusing w_ocr_engine = wolf::ml::ocr::w_ocr_engine;\nusing config_for_ocr_struct = wolf::ml::ocr::config_for_ocr_struct;\nusing w_referee = wolf::ml::ocr::w_referee;\n\nw_soccer::w_soccer() {\n  // LOG_P(w_log_type::W_LOG_INFO, \"creating w_soccer object ...\");\n\n  char *type_1 = new char[30];\n  snprintf(type_1, 30, \"SOCCER_SCREEN_IDENTITY\");\n  screen_identity = set_config(type_1);\n\n  char *type_2 = new char[30];\n  snprintf(type_2, 30, \"SOCCER_RESULT_HOME\");\n  result_home = set_config(type_2);\n  char *type_3 = new char[30];\n  snprintf(type_3, 30, \"SOCCER_RESULT_AWAY\");\n  result_away = set_config(type_3);\n\n  char *type_4 = new char[30];\n  snprintf(type_4, 30, \"SOCCER_NAME_HOME\");\n  name_home = set_config(type_4);\n  char *type_5 = new char[30];\n  snprintf(type_5, 30, \"SOCCER_NAME_AWAY\");\n  name_away = set_config(type_5);\n\n  char *type_6 = new char[30];\n  snprintf(type_6, 30, \"SOCCER_PLATFORM_FREE\");\n  platform_free = set_config_for_ocr(type_6);\n\n  char *type_7 = new char[30];\n  snprintf(type_7, 30, \"SOCCER_PENALTY\");\n  penalty = set_config_for_ocr(type_7);\n\n  delete[] type_1;\n  delete[] type_2;\n  delete[] type_3;\n  delete[] type_4;\n  delete[] type_5;\n  delete[] type_6;\n  delete[] type_7;\n\n  fill_stat_map();\n}\n\nw_soccer::~w_soccer() {}\n\nauto w_soccer::set_config(_In_ char *pType) -> w_ocr_engine::config_struct {\n  std::string type(pType);\n\n  w_ocr_engine::config_struct config;\n\n  config.name = get_env_string((type + \"_WINDOW_NAME\").c_str());\n  config.window = get_env_cv_rect((type + \"_WINDOW\").c_str());\n  config.is_time = get_env_boolean((type + \"_IS_TIME\").c_str());\n  config.config_for_ocr.do_resize_contour =\n      get_env_boolean((type + \"_DO_RESIZE_CONTOUR\").c_str());\n  config.config_for_ocr.gaussian_blur_win_size =\n      get_env_int((type + \"_GAUSSIAN_BLUR_WIN_SIZE\").c_str());\n  config.config_for_ocr.if_store_image_boxes =\n      get_env_boolean((type + \"_IF_STORE_IMAGE_BOXES\").c_str());\n  config.config_for_ocr.is_white =\n      get_env_boolean((type + \"_IS_WHITE\").c_str());\n  config.config_for_ocr.is_digit =\n      get_env_boolean((type + \"_IS_DIGIT\").c_str());\n  config.config_for_ocr.make_white_background =\n      get_env_boolean((type + \"_MAKE_WHITE_BACKGROUND\").c_str());\n  config.config_for_ocr.margin = get_env_int((type + \"_MARGIN\").c_str());\n  config.config_for_ocr.verbose = get_env_boolean((type + \"_VERBOSE\").c_str());\n  config.config_for_ocr.threshold_value =\n      get_env_int((type + \"_THRESHOLD\").c_str());\n  config.config_for_ocr.white_background_threshold =\n      get_env_int((type + \"_WHITE_BACKGROUND_THRESHOLD\").c_str());\n  config.config_for_ocr.restrictions.max_area =\n      get_env_int((type + \"_RESTRICTIONS_MAX_AREA\").c_str());\n  config.config_for_ocr.restrictions.min_area =\n      get_env_int((type + \"_RESTRICTIONS_MIN_AREA\").c_str());\n  config.config_for_ocr.restrictions.max_width =\n      get_env_int((type + \"_RESTRICTIONS_MAX_WIDTH\").c_str());\n  config.config_for_ocr.restrictions.min_width =\n      get_env_int((type + \"_RESTRICTIONS_MIN_WIDTH\").c_str());\n  config.config_for_ocr.restrictions.max_height =\n      get_env_int((type + \"_RESTRICTIONS_MAX_HEIGHT\").c_str());\n  config.config_for_ocr.restrictions.min_height =\n      get_env_int((type + \"_RESTRICTIONS_MIN_HEIGHT\").c_str());\n\n  return config;\n}\n\nauto w_soccer::set_config_for_ocr(_In_ char *pType) -> config_for_ocr_struct {\n  std::string type(pType);\n  config_for_ocr_struct config;\n\n  config.restrictions.max_area =\n      get_env_int((type + \"_RESTRICTIONS_MAX_AREA\").c_str());\n  config.restrictions.min_area =\n      get_env_int((type + \"_RESTRICTIONS_MIN_AREA\").c_str());\n  config.restrictions.max_width =\n      get_env_int((type + \"_RESTRICTIONS_MAX_WIDTH\").c_str());\n  config.restrictions.min_width =\n      get_env_int((type + \"_RESTRICTIONS_MIN_WIDTH\").c_str());\n  config.restrictions.max_height =\n      get_env_int((type + \"_RESTRICTIONS_MAX_HEIGHT\").c_str());\n  config.restrictions.min_height =\n      get_env_int((type + \"_RESTRICTIONS_MIN_HEIGHT\").c_str());\n  config.fraction = get_env_float((type + \"_FRACTION\").c_str());\n\n  return config;\n}\n\nauto w_soccer::fill_stat_map() -> void {\n  stat_first_half = get_env_string(\"SOCCER_STAT_FIRST_HALF_STRING\");\n  stat_second_half = get_env_string(\"SOCCER_STAT_SECOND_HALF_STRING\");\n  stat_extra_first_half = get_env_string(\"SOCCER_STAT_EXTRA_FIRST_HALF_STRING\");\n  stat_extra_second_half =\n      get_env_string(\"SOCCER_STAT_EXTRA_SECOND_HALF_STRING\");\n  stat_penalty = get_env_string(\"SOCCER_STAT_PENALTY_STRING\");\n\n  bool is_platform_free = get_env_boolean(\"SOCCER_GLOBAL_PLATFORM_FREE\");\n\n  stat_map.insert(std::pair<std::string, std::string>(\n      get_first_character_of_string(stat_first_half, is_platform_free),\n      \"first_half\"));\n  stat_map.insert(std::pair<std::string, std::string>(\n      get_first_character_of_string(stat_second_half, is_platform_free),\n      \"second_half\"));\n  stat_map.insert(std::pair<std::string, std::string>(\n      get_first_character_of_string(stat_extra_first_half, is_platform_free),\n      \"extra_first_half\"));\n  stat_map.insert(std::pair<std::string, std::string>(\n      get_first_character_of_string(stat_extra_second_half, is_platform_free),\n      \"extra_second_half\"));\n  stat_map.insert(std::pair<std::string, std::string>(\n      get_first_character_of_string(stat_penalty, is_platform_free),\n      \"penalty\"));\n}\n\nauto w_soccer::extract_result_from_frame_boxes(\n    _In_ cv::Mat &frame, _Inout_ frame_result_struct &frame_data) -> void {\n  std::vector<w_ocr_engine::character_and_center> temp_words, temp_team_names;\n\n  cv::Mat frame_box = frame(screen_identity.window);\n  temp_words =\n      ocr_object.image_to_string(frame_box, screen_identity.config_for_ocr);\n\n  if (temp_words.size() == 1) {\n    if (temp_words[0].text.c_str()[0] == stat_first_half.c_str()[0] ||\n        temp_words[0].text.c_str()[0] == stat_second_half.c_str()[0]) {\n      frame_data.stat = stat_map[temp_words[0].text];\n      temp_words.clear();\n\n      frame_box = frame(result_home.window);\n      temp_words =\n          ocr_object.image_to_string(frame_box, result_home.config_for_ocr);\n      if (temp_words.size() != 0) {\n        frame_data.home_result = temp_words[0];\n\n        frame_box = frame(result_away.window);\n        temp_words =\n            ocr_object.image_to_string(frame_box, result_away.config_for_ocr);\n        if (temp_words.size() != 0) {\n          frame_data.away_result = temp_words[0];\n\n          temp_team_names.clear();\n\n          frame_box = frame(name_home.window);\n          temp_team_names =\n              ocr_object.image_to_string(frame_box, name_home.config_for_ocr);\n          if (temp_team_names.size() == 0) {\n            frame_box.release();\n            return;\n          }\n          frame_data.home_name = concatenate_name_result(temp_team_names);\n\n          frame_box = frame(name_away.window);\n          temp_team_names =\n              ocr_object.image_to_string(frame_box, name_away.config_for_ocr);\n          if (temp_team_names.size() == 0) {\n            frame_box.release();\n            return;\n          }\n          frame_data.away_name = concatenate_name_result(temp_team_names);\n        }\n      }\n    }\n  }\n  frame_box.release();\n}\n\nauto w_soccer::extract_result_based_on_clusters_symmetricity(\n    _In_ cv::Mat &frame, _Inout_ frame_result_struct &frame_data) -> void {\n  cv::Mat cloned_image = frame.clone();\n  int image_width = frame.cols;\n\n  if (get_env_boolean(\"CONFIG_STORE_LATEST_FRAME\")) {\n    std::string image_data_file_name =\n        get_env_string(\"SOCCER_GLOBAL_LOG_FILE\") + \"_\" +\n        std::to_string(frame_number % 10);\n    std::ofstream ofs(image_data_file_name.c_str(), std::ofstream::out);\n    ofs.write((char *)frame.data,\n              frame.total() * frame.channels() * sizeof(uint8_t));\n    ofs.close();\n  }\n\n  std::vector<std::vector<w_ocr_engine::characters_struct>> digits_candidates;\n  std::vector<std::vector<w_ocr_engine::characters_struct>> words_candidates;\n  std::vector<std::vector<w_ocr_engine::characters_struct>> time_candidates;\n\n  extract_all_image_char_clusters(cloned_image, digits_candidates,\n                                  words_candidates, time_candidates);\n\n  if (digits_candidates.size() == 2 && words_candidates.size() == 2 &&\n      time_candidates.size() == 1) {\n    for (int i = 0; i < words_candidates.size(); i++) {\n      std::vector<w_ocr_engine::character_and_center> text_of_cluster =\n          ocr_object.char_vec_to_string(words_candidates[i], frame,\n                                        name_home.config_for_ocr);\n\n      if (text_of_cluster.size() > 0) {\n        if (text_of_cluster[0].center.x < image_width / 2) {\n          frame_data.home_name = text_of_cluster[0];\n        } else {\n          frame_data.away_name = text_of_cluster[0];\n        }\n      }\n    }\n    for (int i = 0; i < digits_candidates.size(); i++) {\n      std::vector<w_ocr_engine::character_and_center> text_of_cluster =\n          ocr_object.char_vec_to_string(digits_candidates[i], frame,\n                                        result_home.config_for_ocr);\n      if (text_of_cluster.size() > 0) {\n        if (text_of_cluster[0].center.x < image_width / 2) {\n          frame_data.home_result = text_of_cluster[0];\n        } else {\n          frame_data.away_result = text_of_cluster[0];\n        }\n      }\n    }\n    for (int i = 0; i < time_candidates.size(); i++) {\n      std::vector<w_ocr_engine::character_and_center> text_of_cluster =\n          ocr_object.char_vec_to_string(time_candidates[i], frame,\n                                        screen_identity.config_for_ocr);\n      if (text_of_cluster.size() > 0) {\n        frame_data.stat = get_nearest_string(text_of_cluster[0].text, stat_map);\n        if (frame_data.stat.compare(\"\") == 0) {\n          w_ocr_engine::config_struct temp_screen_identity = screen_identity;\n          temp_screen_identity.config_for_ocr.is_digit = false;\n          text_of_cluster = ocr_object.char_vec_to_string(\n              time_candidates[i], frame, temp_screen_identity.config_for_ocr);\n          std::vector<std::string> temp_result =\n              split_string(text_of_cluster[0].text, ' ');\n          if (temp_result.size() > 1) {\n            frame_data.stat = get_nearest_string(temp_result[1], stat_map);\n          }\n        }\n        if (frame_data.stat.compare(\"\") != 0) {\n          extract_penalty_result_symmetricity(frame, digits_candidates,\n                                              words_candidates, time_candidates,\n                                              frame_data);\n          // frame_data.stat = stat_map[frame_data.stat];\n        }\n      }\n    }\n  }\n  cloned_image.release();\n}\n\nauto w_soccer::extract_penalty_result_symmetricity(\n    _In_ cv::Mat &frame,\n    _In_ std::vector<std::vector<w_ocr_engine::characters_struct>>\n        digits_candidates,\n    _In_ std::vector<std::vector<w_ocr_engine::characters_struct>>\n        words_candidates,\n    _In_ std::vector<std::vector<w_ocr_engine::characters_struct>>\n        time_candidates,\n    _Inout_ frame_result_struct &frame_data) -> void {\n  if (frame_data.stat.compare(get_env_string(\"SOCCER_STAT_CHECK_PENALTY\")) !=\n          0 ||\n      digits_candidates.size() != 2 || time_candidates.size() != 1) {\n    return;\n  }\n  cv::Rect result_box_bound_rect;\n\n  if (stat_second_half.compare(get_env_string(\"SOCCER_STAT_CHECK_PENALTY\")) ==\n      0) {\n    w_ocr_engine::characters_struct left, right;\n    left = (digits_candidates[0][0].bound_rect.x >\n            digits_candidates[1][0].bound_rect.x)\n               ? digits_candidates[1][digits_candidates[1].size() - 1]\n               : digits_candidates[0][digits_candidates[0].size() - 1];\n    right = (digits_candidates[0][0].bound_rect.x >\n             digits_candidates[1][0].bound_rect.x)\n                ? digits_candidates[0][0]\n                : digits_candidates[1][0];\n\n    result_box_bound_rect.x = left.bound_rect.x + left.bound_rect.width;\n    result_box_bound_rect.width = right.bound_rect.x - result_box_bound_rect.x;\n\n    if (result_box_bound_rect.width < 0) {\n      std::cout << \"something went wrong!!!\" << std::endl;\n      return;\n    }\n\n    if (result_box_bound_rect.width > frame.cols / 3) {\n      return;\n    }\n\n    result_box_bound_rect.y =\n        left.bound_rect.y + left.bound_rect.height / 2 + 4;\n    result_box_bound_rect.height = left.bound_rect.height / 2;\n  } else if (stat_penalty.compare(\n                 get_env_string(\"SOCCER_STAT_CHECK_PENALTY\")) == 0) {\n    result_box_bound_rect.x = time_candidates[0][0].bound_rect.x - 50;\n    result_box_bound_rect.width = 50 + 10;\n    // (time_candidates[0][time_candidates[0].size() - 1].bound_rect.x +\n    //  time_candidates[0][time_candidates[0].size() - 1].bound_rect.width -\n    //  result_box_bound_rect.x) /\n    // 2;\n    result_box_bound_rect.y = time_candidates[0][0].bound_rect.y;\n    result_box_bound_rect.height = time_candidates[0][0].bound_rect.height;\n  }\n\n  cv::Mat result_box;\n  frame(result_box_bound_rect).copyTo(result_box);\n\n  // cv::imshow(\"image\", result_box);\n  // cv::waitKey();\n\n  std::vector<w_ocr_engine::character_and_center> temp_words;\n\n  temp_words =\n      ocr_object.image_to_string(result_box, result_away.config_for_ocr);\n\n  if (temp_words.size() == 2 && stat_second_half.compare(get_env_string(\n                                    \"SOCCER_STAT_CHECK_PENALTY\")) == 0) {\n    frame_data.home_penalty_result =\n        (temp_words[0].center.x < temp_words[1].center.x) ? temp_words[0]\n                                                          : temp_words[1];\n    frame_data.away_penalty_result =\n        (temp_words[0].center.x < temp_words[1].center.x) ? temp_words[1]\n                                                          : temp_words[0];\n  } else if (temp_words.size() == 1 && stat_penalty.compare(get_env_string(\n                                           \"SOCCER_STAT_CHECK_PENALTY\")) == 0) {\n    std::vector<std::string> temp_result =\n        split_string(temp_words[0].text, ' ');\n    frame_data.home_penalty_result.text = temp_result[0];\n    frame_data.away_penalty_result.text = temp_result[1];\n  }\n\n  return;\n}\n\nauto w_soccer::single_image_result_extraction(_In_ uint8_t *pRawImage,\n                                              _In_ int height, _In_ int width,\n                                              _In_ ocr_callback *callback)\n    -> int {\n  int desired_height = get_env_int(\"SOCCER_GLOBAL_FRAME_HEIGHT\");\n  int desired_width = get_env_int(\"SOCCER_GLOBAL_FRAME_WIDTH\");\n  if (!pRawImage || height != desired_height || width != desired_width) {\n    return 1;\n  }\n  cv::Mat original_image = cv::Mat(height, width, CV_8UC3, pRawImage);\n\n  frame_result_struct temp_frame_data;\n\n  if (get_env_boolean(\"SOCCER_GLOBAL_PLATFORM_FREE\")) {\n    extract_result_based_on_clusters_symmetricity(original_image,\n                                                  temp_frame_data);\n  } else {\n    extract_result_from_frame_boxes(original_image, temp_frame_data);\n  }\n\n  if (temp_frame_data.stat.compare(\"\") != 0 &&\n      temp_frame_data.home_result.text.compare(\"\") != 0 &&\n      temp_frame_data.away_result.text.compare(\"\") != 0 &&\n      temp_frame_data.home_name.text.compare(\"\") != 0 &&\n      temp_frame_data.away_name.text.compare(\"\") != 0) {\n    temp_frame_data.frame_number = frame_number;\n    cv::Mat temp_image = original_image.clone();\n    update_match_data(temp_frame_data, temp_image);\n    temp_image.release();\n  }\n\n  // update the frame number\n  frame_number += 1;\n  for (int i = 0; i < matches_data.size(); i++) {\n    if (i == 0 && frame_number < matches_data[i].frame_number + 10) {\n      continue;\n    }\n    matches_data[i].ready = true;\n  }\n\n  extract_game_results();\n\n  if (callback) {\n    for (int i = 0; i < matches_data.size(); i++) {\n      if (matches_data[i].extracted && !matches_data[i].applied) {\n        std::string str_result = matches_data[i].stat + \",\" +\n                                 matches_data[i].home_name.text + \",\" +\n                                 matches_data[i].home_result.text + \",\" +\n                                 matches_data[i].away_name.text + \",\" +\n                                 matches_data[i].away_result.text;\n        if (matches_data[i].home_penalty_result.text.compare(\"\") != 0 &&\n            matches_data[i].away_penalty_result.text.compare(\"\") != 0) {\n          str_result = str_result + \",\" +\n                       matches_data[i].home_penalty_result.text + \",\" +\n                       matches_data[i].away_penalty_result.text;\n        }\n        char *char_result = new char[256];\n        strcpy(char_result, str_result.c_str());\n\n        callback(char_result, 256, matches_data[i].result_image.data,\n                 matches_data[i].result_image.cols,\n                 matches_data[i].result_image.rows);\n        the_last_result_message = str_result;\n\n        matches_data[i].applied = true;\n      }\n    }\n  }\n\n  return 0;\n}\n\nauto w_soccer::extract_all_image_char_clusters(\n    cv::Mat &image,\n    std::vector<std::vector<w_ocr_engine::characters_struct>>\n        &digits_candidates,\n    std::vector<std::vector<w_ocr_engine::characters_struct>> &words_candidates,\n    std::vector<std::vector<w_ocr_engine::characters_struct>> &time_candidates)\n    -> void {\n  cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);\n  int global_threshold = get_env_int(\"SOCCER_GLOBAL_THRESHOLD\");\n  cv::threshold(image, image, global_threshold, 255,\n                cv::THRESH_BINARY); // cv::THRESH_OTSU);\n\n  std::vector<std::vector<cv::Point>> contours;\n  std::vector<cv::Vec4i> hierarchy;\n\n  cv::findContours(image, contours, hierarchy, cv::RETR_TREE,\n                   cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));\n  std::vector<w_ocr_engine::characters_struct> modified_bounding_rects =\n      ocr_object.contours_to_char_structs(contours);\n\n  modified_bounding_rects = ocr_object.filter_chars_by_contour_size(\n      modified_bounding_rects, platform_free);\n  contours.clear();\n  hierarchy.clear();\n\n  ocr_object.merge_overlapped_contours(modified_bounding_rects, platform_free);\n\n  std::vector<std::vector<w_ocr_engine::characters_struct>>\n      clustered_characters = ocr_object.cluster_char_structs(\n          modified_bounding_rects, platform_free);\n\n  int ref_index = clustered_characters.size();\n  for (int i = 0; i < ref_index; i++) {\n    int index = ref_index - (i + 1);\n    if (clustered_characters[index].size() < 3 &&\n        ocr_object.same_level(clustered_characters[index])) {\n      digits_candidates.push_back(clustered_characters[index]);\n    }\n    if (clustered_characters[index].size() >= 3 &&\n        ocr_object.same_level(clustered_characters[index])) {\n      words_candidates.push_back(clustered_characters[index]);\n    }\n    if (clustered_characters[index][0].bound_rect.x < image.cols / 2 &&\n        clustered_characters[index][clustered_characters[index].size() - 1]\n                .bound_rect.x > image.cols / 2 &&\n        clustered_characters[index].size() < 16 &&\n        clustered_characters[index].size() > 1) {\n      time_candidates.push_back(clustered_characters[index]);\n    }\n  }\n  // cv::Mat temp_image = cv::Mat(image.rows, image.cols, CV_8UC1,\n  // cv::Scalar(0)); for (int i = 0; i < clustered_characters.size(); i++)\n  // {\n  // \tocr_object.show_contours(temp_image, clustered_characters[i], \"Hello\",\n  // true);\n  // }\n\n  clustered_characters.clear();\n\n  ocr_object.keep_twins(words_candidates, image.cols, image.rows, true);\n  ocr_object.keep_twins(digits_candidates, image.cols, image.rows, false);\n  ocr_object.keep_time(time_candidates);\n\n  for (int i = 0; i < digits_candidates.size(); i++) {\n    for (size_t j = 0; j < digits_candidates[i].size(); j++) {\n      ocr_object.margin_bounding_rect(digits_candidates[i][j].bound_rect,\n                                      platform_free.margin, image);\n    }\n  }\n\n  for (int i = 0; i < words_candidates.size(); i++) {\n    for (size_t j = 0; j < words_candidates[i].size(); j++) {\n      ocr_object.margin_bounding_rect(words_candidates[i][j].bound_rect,\n                                      platform_free.margin, image);\n    }\n  }\n\n  for (int i = 0; i < time_candidates.size(); i++) {\n    for (size_t j = 0; j < time_candidates[i].size(); j++) {\n      ocr_object.margin_bounding_rect(time_candidates[i][j].bound_rect,\n                                      platform_free.margin, image);\n    }\n  }\n\n  return;\n}\n\nauto w_soccer::replace_team_names_with_most_similar_string(\n    _Inout_ std::vector<w_referee::match_result_struct> &result) -> void {\n  for (int i = 0; i < int(result.size()); i++) {\n    // LOG_P(w_log_type::W_LOG_INFO, \"recognized home name : %s\",\n    // result[i].home_name.text); LOG_P(w_log_type::W_LOG_INFO, \"recognized away\n    // name : %s\", result[i].away_name.text);\n    std::string path = get_env_string(\"SIMILAR_STRINGS_FILE_PATH\");\n    result[i].home_name.text =\n        get_nearest_string(result[i].home_name.text, path);\n    result[i].away_name.text =\n        get_nearest_string(result[i].away_name.text, path);\n    // LOG_P(w_log_type::W_LOG_INFO, \"recognized home name after replace with\n    // most similar: %s\", result[i].home_name.text);\n    // LOG_P(w_log_type::W_LOG_INFO, \"recognized away name after replace with\n    // most similar: %s\", result[i].away_name.text);\n  }\n}\n\nauto w_soccer::initial_match_result_struct(\n    w_referee::frame_result_struct frame_data, cv::Mat &image)\n    -> w_referee::match_result_struct {\n  w_referee::match_result_struct temp_match_data;\n  temp_match_data.all_frames_results.push_back(frame_data);\n  temp_match_data.stat = frame_data.stat;\n  temp_match_data.result_image = image;\n  temp_match_data.frame_number = frame_data.frame_number;\n\n  return temp_match_data;\n}\n\nauto w_soccer::update_match_data(_In_ w_referee::frame_result_struct frame_data,\n                                 _In_ cv::Mat &image) -> void {\n  if (matches_data.size() == 0 ||\n      frame_data.frame_number >\n          matches_data[matches_data.size() - 1].frame_number + 10) {\n    matches_data.push_back(initial_match_result_struct(frame_data, image));\n  } else {\n    matches_data[matches_data.size() - 1].frame_number =\n        frame_data.frame_number;\n    matches_data[matches_data.size() - 1].all_frames_results.push_back(\n        frame_data);\n  }\n}\n\nauto w_soccer::extract_game_results() -> void {\n  w_referee ocr_object;\n\n  for (int i = 0; i < matches_data.size(); i++) {\n    int min_frames = get_env_int(\"SOCCER_GLOBAL_MIN_FRAMES\");\n    if (!matches_data[i].ready || matches_data[i].extracted ||\n        matches_data[i].all_frames_results.size() < min_frames) {\n      continue;\n    }\n    w_referee::frame_result_struct temp_frame_result;\n    ocr_object.voting_over_results_and_names(\n        temp_frame_result, matches_data[i].all_frames_results);\n\n    if (get_env_boolean(\"SIMILARITY_USE_FOR_TEAM_NAMES\")) {\n      std::string path = get_env_string(\"SIMILAR_STRINGS_FILE_PATH\");\n      temp_frame_result.away_name.text =\n          get_nearest_string(temp_frame_result.away_name.text, path);\n      temp_frame_result.home_name.text =\n          get_nearest_string(temp_frame_result.home_name.text, path);\n    }\n\n    matches_data[i].extracted = true;\n    matches_data[i].away_name = temp_frame_result.away_name;\n    matches_data[i].away_result = temp_frame_result.away_result;\n    matches_data[i].home_name = temp_frame_result.home_name;\n    matches_data[i].home_result = temp_frame_result.home_result;\n    matches_data[i].home_penalty_result = temp_frame_result.home_penalty_result;\n    matches_data[i].away_penalty_result = temp_frame_result.away_penalty_result;\n  }\n}\n\nauto w_soccer::get_matches_data()\n    -> std::vector<w_referee::match_result_struct> {\n  return matches_data;\n}\n\nauto w_soccer::get_stat_map() -> std::map<std::string, std::string> {\n  return stat_map;\n}\n"
  },
  {
    "path": "wolf/ml/referee_ocr/w_soccer.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <fstream>\n#include <iostream>\n#include <map>\n\n#include \"salieri.h\"\n#include \"w_image_processor.hpp\"\n#include \"w_ocr_engine.hpp\"\n#include \"w_referee.hpp\"\n#include \"wolf.hpp\"\n\ntypedef void ocr_callback(char *result_buffer, int result_buffer_size,\n                          uint8_t *image_buffer, int image_width,\n                          int image_height);\n\nnamespace wolf::ml::ocr {\n\n//! w_soccer class.\n/*! \\brief It is extract the soccer game result.\n\n        This class contains functions, structures, and variables that use the\n   w_soccer class for doing referee purposes.\n*/\nclass w_soccer : public w_referee {\npublic:\n  /*!\n          The constructor of the class.\n          In the constructor the configs are set.\n\n          \\return\n  */\n  W_API w_soccer();\n\n  /*!\n          The deconstructor of the class.\n\n          The function is empty.\n  */\n  W_API ~w_soccer();\n\n  /*!\n  The function return the config of desired image window.\n\n          \\param pType The type of box\n          \\return\n  */\n  W_API static auto set_config(_In_ char *pType) -> w_ocr_engine::config_struct;\n\n  /*!\n          The function set the stat map global variable by dotenvs information.\n  */\n  auto fill_stat_map() -> void;\n\n  W_API auto set_config_for_ocr(_In_ char *pType) -> config_for_ocr_struct;\n\n  /*!\n          The function returns frame results, the results are extracted from\n     pre-defined frame boxes.\n\n          \\param frame The input frame image.\n          \\param frame_data The frame result would be stored in the frame_date.\n          \\return Void\n  */\n  W_API auto extract_result_from_frame_boxes(\n      _In_ cv::Mat &frame, _Inout_ frame_result_struct &frame_data) -> void;\n\n  /*!\n          The function returns frame results, the results are extracted based on\n     the character clusters' symmetricity.\n\n          \\param frame The input frame image.\n          \\param frame_data The frame result would be stored in the frame_date.\n          \\return Void\n  */\n  W_API auto extract_result_based_on_clusters_symmetricity(\n      _In_ cv::Mat &frame, _Inout_ frame_result_struct &frame_data) -> void;\n\n  /*!\n          The function checks for penalty results and if the scene contains the\n     penalty results the results would be extracted.\n\n          \\param frame The input frame image.\n          \\param digits_candidates The cluster of digits characters.\n          \\param words_candidates The cluster of words characters.\n          \\param time_candidates The cluster of time stat related characters.\n          \\param frame_data The frame result would be stored in the frame_date.\n          \\return Void\n  */\n  W_API auto extract_penalty_result_symmetricity(\n      _In_ cv::Mat &frame,\n      _In_ std::vector<std::vector<w_ocr_engine::characters_struct>>\n          digits_candidates,\n      _In_ std::vector<std::vector<w_ocr_engine::characters_struct>>\n          words_candidates,\n      _In_ std::vector<std::vector<w_ocr_engine::characters_struct>>\n          time_candidates,\n      _Inout_ frame_result_struct &frame_data) -> void;\n\n  /*!\n  The function returns the game results, if the image contains the game final\n  result.\n\n          \\param pRawImage The sequence of the input image pixels array in BGR\n  format. \\param height The image height. \\param width The image width. \\param\n  pStr The image result. \\return Void\n  */\n  W_API auto single_image_result_extraction(_In_ uint8_t *pRawImage,\n                                            _In_ int height, _In_ int width,\n                                            _In_ ocr_callback *callback) -> int;\n\n  /*!\n  The extract_all_image_char_clusters function returns the character cluster\n  related to the frame result.\n\n          \\param pImage The input image.\n          \\param pDdigitsCandidates The character clusters of the result texts.\n          \\param pWordsCandidates The character clusters of the team name texts.\n          \\param pTimeCandidates The character cluster of the stat texts.\n          \\return Void\n  */\n  W_API auto extract_all_image_char_clusters(\n      cv::Mat &pImage,\n      std::vector<std::vector<w_ocr_engine::characters_struct>>\n          &pDigitsCandidates,\n      std::vector<std::vector<w_ocr_engine::characters_struct>>\n          &pWordsCandidates,\n      std::vector<std::vector<w_ocr_engine::characters_struct>>\n          &pTimeCandidates) -> void;\n\n  /*!\n  replace team names stored in match_result_struct using string similarity\n  algorithms.\n\n          \\param result input struct\n          \\return\n  */\n  W_API static auto replace_team_names_with_most_similar_string(\n      _Inout_ std::vector<w_referee::match_result_struct> &result) -> void;\n\n  /*!\n  The initial_match_result_struct function fills a match_result_struct with the\n  initial values.\n\n          \\param frame_data input struct\n          \\param image input struct\n          \\return An initialed variable of match data structure.\n  */\n  W_API auto\n  initial_match_result_struct(w_referee::frame_result_struct frame_data,\n                              cv::Mat &image) -> w_referee::match_result_struct;\n\n  /*!\n  The update_match_data function store frames data in the match_date variable.\n\n          \\param frame_data input struct\n          \\param image input struct\n          \\return\n  */\n  W_API auto update_match_data(_In_ w_referee::frame_result_struct frame_data,\n                               _In_ cv::Mat &image) -> void;\n\n  /*!\n  The extract_game_results function extracts the game results from the\n  match_data and stores the results in the match_data.\n\n          \\return\n  */\n  W_API auto extract_game_results() -> void;\n\n  /*!\n  The get_matches_data function returns the private match_data variable.\n\n          \\return The private match_data variable.\n  */\n  W_API auto get_matches_data() -> std::vector<w_referee::match_result_struct>;\n\n  /*!\n          The get_stat_map function returns the private stat_map variable.\n\n          \\return The private stat_map variable.\n  */\n  W_API auto get_stat_map() -> std::map<std::string, std::string>;\n\nprivate:\n  /*!<The number of frame.*/\n  int frame_number = 0;\n  /*!<The configuration of the screen_identity window.*/\n  w_ocr_engine::config_struct screen_identity;\n  /*!<The configuration of the result_home window.*/\n  w_ocr_engine::config_struct result_home;\n  /*!<The configuration of the result_away window.*/\n  w_ocr_engine::config_struct result_away;\n  /*!<The configuration of the name_home window.*/\n  w_ocr_engine::config_struct name_home;\n  /*!<The configuration of the name_away window.*/\n  w_ocr_engine::config_struct name_away;\n  /*!<The configuration of the platform_free.*/\n  config_for_ocr_struct platform_free;\n  /*!<The configuration of the penalty.*/\n  config_for_ocr_struct penalty;\n\n  /*!<The matches data contains the results of the games.*/\n  std::vector<w_referee::match_result_struct> matches_data;\n\n  /*!<Game stat like first-half, second-half, and ... .*/\n  std::string stat_first_half;\n  std::string stat_second_half;\n  std::string stat_extra_first_half;\n  std::string stat_extra_second_half;\n  std::string stat_penalty;\n\n  std::map<std::string, std::string> stat_map;\n\n  std::string the_last_result_message = \"\";\n\n  /*!<An object of w_ocr_engine class.*/\n  w_ocr_engine ocr_object;\n};\n} // namespace wolf::ml::ocr"
  },
  {
    "path": "wolf/ml/referee_ocr/w_utilities.cpp",
    "content": "#include \"w_utilities.hpp\"\n\n#include <rapidjson/document.h>\n#include <rapidjson/istreamwrapper.h>\n#include <rapidjson/ostreamwrapper.h>\n#include <rapidjson/stringbuffer.h>\n#include <rapidjson/writer.h>\n\n#include <algorithm>\n#include <cctype>\n#include <cstdlib>\n#include <filesystem>\n#include <fstream>\n#include <iomanip>\n#include <iostream>\n#include <numeric>\n#include <opencv2/opencv.hpp>\n#include <sstream>\n#include <string>\n#include <vector>\n\n// #include \"spdlog/sinks/basic_file_sink.h\"\n// #include \"spdlog/sinks/stdout_color_sinks.h\"\n// #include \"spdlog/spdlog.h\"\nnamespace fs = std::filesystem;\n#ifdef __TELEMETRY\n#include \"opentelemetry/sdk/version/version.h\"\n#include \"opentelemetry/trace/provider.h\"\n\nnamespace trace = opentelemetry::trace;\nnamespace nostd = opentelemetry::nostd;\n\nnamespace {\nnostd::shared_ptr<trace::Tracer> get_tracer() {\n  auto provider = trace::Provider::GetTracerProvider();\n  return provider->GetTracer(\"pes_21\", OPENTELEMETRY_SDK_VERSION);\n}\n} // namespace\n#endif\n\nnamespace wolf::ml::ocr {\n\nauto get_nearest_string(_In_ std::string pInput, std::string pFilePath)\n    -> std::string {\n  // LOG_P(w_log_type::W_LOG_INFO, \"path to similar strings file: %s\",\n  // pFilePath);\n  std::ifstream similar_strings(pFilePath);\n  float threshold = get_env_float(\"SIMILARITY_THRESHOLD\");\n  // LOG_P(w_log_type::W_LOG_INFO, \"similarity threshold: %f\", threshold);\n  std::string candidate_string;\n  float best_similarity = 0;\n  std::string most_similar;\n\n  if (pInput.length() == 0) {\n    return pInput;\n  }\n\n  while (std::getline(similar_strings, candidate_string)) {\n    float similarity =\n        normalized_levenshtein_similarity(pInput, candidate_string);\n    if (similarity > best_similarity) {\n      most_similar = candidate_string;\n      best_similarity = similarity;\n    }\n  }\n\n  if (best_similarity > threshold) {\n    return most_similar;\n  } else {\n    return pInput;\n  }\n}\n\nauto get_nearest_string(_In_ std::string pInput,\n                        _In_ std::map<std::string, std::string> pMap)\n    -> std::string\n\n{\n  float threshold = get_env_float(\"SIMILARITY_THRESHOLD_STAT\");\n  // LOG_P(w_log_type::W_LOG_INFO, \"similarity threshold: %f\", threshold);\n  std::string candidate_string;\n  float best_similarity = 0;\n  std::string most_similar;\n\n  if (pInput.length() == 0) {\n    return pInput;\n  }\n\n  for (auto it = pMap.begin(); it != pMap.end(); it++) {\n    candidate_string = it->first;\n    float similarity =\n        normalized_levenshtein_similarity(pInput, candidate_string);\n    if (similarity > best_similarity) {\n      most_similar = candidate_string;\n      best_similarity = similarity;\n    }\n  }\n\n  if (best_similarity > threshold) {\n    return most_similar;\n  } else {\n    return \"\";\n  }\n}\n\nstd::string get_value_from_json_file_by_key(std::string pJsonFilePath,\n                                            std::string pKey) {\n#ifdef __TELEMETRY\n  auto span = get_tracer()->StartSpan(\"get_value_from_json_file_by_key\");\n#endif\n  using namespace rapidjson;\n\n  std::ifstream ifs{pJsonFilePath};\n  if (!ifs.is_open()) {\n    fs::path cwd = fs::current_path();\n    // spdlog::error(\"current path {}\", cwd.string());\n    // spdlog::error(\"Could not open {} file for reading!\", pJsonFilePath);\n    std::exit(ENOENT);\n  }\n\n  IStreamWrapper isw{ifs};\n\n  Document doc{};\n  doc.ParseStream(isw);\n  std::string out = doc[pKey.c_str()].GetString();\n\n  return out;\n}\n\nstd::vector<int>\nline_of_numbers_in_string_to_vector_of_integers(std::string pVariable) {\n#ifdef __TELEMETRY\n  auto span = get_tracer()->StartSpan(\n      \"line_of_numbers_in_string_to_vector_of_integers\");\n#endif\n  std::vector<int> result;\n\n  std::vector<std::string> temp = split_string(pVariable, ',');\n  for (int i = 0; i < temp.size(); i++) {\n    result.push_back(std::stoi(temp[i]));\n  }\n\n  return result;\n}\n\nauto normalized_levenshtein_similarity(_In_ const std::string &s1,\n                                       _In_ const std::string &s2) -> float {\n  const size_t m = s1.size();\n  const size_t n = s2.size();\n  int distance;\n  if (m == 0 && n == 0)\n    return 0;\n  else if (m == 0)\n    distance = n;\n  else if (n == 0)\n    distance = m;\n  else {\n    std::vector<size_t> costs(n + 1);\n    std::iota(costs.begin(), costs.end(), 0);\n    size_t i = 0;\n    for (auto c1 : s1) {\n      costs[0] = i + 1;\n      size_t corner = i;\n      size_t j = 0;\n      for (auto c2 : s2) {\n        size_t upper = costs[j + 1];\n        costs[j + 1] = (c1 == c2)\n                           ? corner\n                           : 1 + std::min(std::min(upper, corner), costs[j]);\n        corner = upper;\n        ++j;\n      }\n      ++i;\n    }\n    distance = costs[n];\n  }\n  float max = std::max(s1.length(), s2.length());\n  float normalized_distance = distance / max;\n  return 1 - normalized_distance;\n}\n\nauto read_text_file_line_by_line(_In_ std::string pFilePath)\n    -> std::vector<std::string> {\n#ifdef __TELEMETRY\n  auto span =\n      trace::Scope(get_tracer()->StartSpan(\"read_text_file_line_by_line\"));\n#endif\n  std::vector<std::string> lines;\n  std::string line;\n\n  std::ifstream input_file(pFilePath);\n  if (!input_file.is_open()) {\n    std::cerr << \"Could not open the file - '\" << pFilePath << \"'\" << std::endl;\n    return lines;\n  }\n\n  while (std::getline(input_file, line)) {\n    lines.push_back(line);\n  }\n\n  input_file.close();\n  return lines;\n}\n\nbool replace_string(std::string &str, const std::string &from,\n                    const std::string &to) {\n  size_t start_pos = str.find(from);\n  if (start_pos == std::string::npos)\n    return false;\n  str.replace(start_pos, from.length(), to);\n  return true;\n}\n\nstd::vector<std::string> split_string(std::string input_string,\n                                      char reference) {\n#ifdef __TELEMETRY\n  auto scoped_span = trace::Scope(get_tracer()->StartSpan(\"split_string\"));\n  // auto scoped_span = get_tracer()->StartSpan(\"split_string\");\n#endif\n  std::stringstream test(input_string);\n  std::string segment;\n  std::vector<std::string> seglist;\n\n  while (std::getline(test, segment, reference)) {\n    seglist.push_back(segment);\n  }\n\n  return seglist;\n}\n\nbool string_2_boolean(std::string pVariable) {\n#ifdef __TELEMETRY\n  auto span = get_tracer()->StartSpan(\"string_2_boolean\");\n#endif\n  bool result;\n  std::transform(pVariable.begin(), pVariable.end(), pVariable.begin(),\n                 ::tolower);\n\n  if (pVariable.compare(\"true\") == 0 || pVariable.compare(\"false\") == 0) {\n    std::istringstream is(pVariable);\n    is >> std::boolalpha >> result;\n  } else {\n    throw std::runtime_error(\n        \"Invalid input, the input must be 'true' or 'false' not \" + pVariable);\n  }\n\n  return result;\n}\n\nauto store_image_in_folder(\n    _In_ std::vector<w_referee::match_result_struct> &pVideoResult,\n    _In_ std::string pOutputImageFolderPath, _In_ std::string pVideoPath)\n    -> void {\n#ifdef __TELEMETRY\n  auto span = get_tracer()->StartSpan(\"store_image_in_folder\");\n#endif\n  fs::path temp_video_path = pVideoPath;\n  std::string temp_name = temp_video_path.filename().string();\n  std::string video_name = split_string(temp_name, '.')[0];\n\n  for (size_t i = 0; i < pVideoResult.size(); i++) {\n    fs::path out_path = pOutputImageFolderPath + \"/\" + video_name + \"_\" +\n                        std::to_string(i) + \".png\";\n    cv::imwrite(out_path.string().c_str(), pVideoResult[i].result_image);\n    cv::waitKey(300);\n    pVideoResult[i].release();\n  }\n\n  return;\n}\n\nvoid write_in_file_append(std::string file_path, std::string content) {\n#ifdef __TELEMETRY\n  auto scoped_span =\n      trace::Scope(get_tracer()->StartSpan(\"write_in_file_append\"));\n  // auto scoped_span = get_tracer()->StartSpan(\"write_in_file_append\");\n#endif\n\n  std::ofstream file;\n\n  file.open(file_path, std::ios_base::app); // append instead of overwrite\n  file << content << std::endl;\n\n  file.close();\n  return;\n}\n\nvoid write_in_file(std::string file_path, std::string content) {\n#ifdef __TELEMETRY\n  auto scoped_span =\n      trace::Scope(get_tracer()->StartSpan(\"write_in_file_append\"));\n  // auto scoped_span = get_tracer()->StartSpan(\"write_in_file_append\");\n#endif\n\n  std::ofstream file;\n\n  file.open(file_path); // overwrite\n  file << content << std::endl;\n\n  file.close();\n  return;\n}\n\nauto write_results_in_file(\n    _In_ std::vector<w_referee::match_result_struct> &pVideoResult,\n    _In_ std::string pOutputTextPath) -> void {\n#ifdef __TELEMETRY\n  auto span = trace::Scope(get_tracer()->StartSpan(\"write_results_in_file\"));\n#endif\n  for (size_t i = 0; i < pVideoResult.size(); i++) {\n    if (pVideoResult[i].home_penalty_result.text.compare(\"\") != 0 &&\n        pVideoResult[i].away_penalty_result.text.compare(\"\") != 0) {\n      write_in_file_append(pOutputTextPath,\n                           pVideoResult[i].stat + \",\" +\n                               pVideoResult[i].home_name.text + \",\" +\n                               pVideoResult[i].home_result.text + \",\" +\n                               pVideoResult[i].away_name.text + \",\" +\n                               pVideoResult[i].away_result.text + \",\" +\n                               pVideoResult[i].home_penalty_result.text + \",\" +\n                               pVideoResult[i].away_penalty_result.text + \",\" +\n                               std::to_string(pVideoResult[i].frame_number));\n    } else {\n      write_in_file_append(pOutputTextPath,\n                           pVideoResult[i].stat + \",\" +\n                               pVideoResult[i].home_name.text + \",\" +\n                               pVideoResult[i].home_result.text + \",\" +\n                               pVideoResult[i].away_name.text + \",\" +\n                               pVideoResult[i].away_result.text + \",\" +\n                               std::to_string(pVideoResult[i].frame_number));\n    }\n  }\n\n  return;\n}\n\nauto is_line_contains_variable(const std::string pStr) -> bool {\n#ifdef __TELEMETRY\n  auto span =\n      trace::Scope(get_tracer()->StartSpan(\"is_line_contains_variable\"));\n#endif\n  bool decision = false;\n  if (pStr.size() > 0) {\n    if (pStr.at(0) != '#' && pStr.size() > 2) {\n      decision = true;\n    }\n  }\n  return decision;\n}\n\nauto set_env(_In_ const char *pDotEnvFilePath) -> void {\n#ifdef __TELEMETRY\n  auto span = trace::Scope(get_tracer()->StartSpan(\"set_env\"));\n#endif\n  std::string env_file_path(pDotEnvFilePath);\n  auto lines = read_text_file_line_by_line(env_file_path);\n\n  std::vector<std::vector<std::string>> env_vector;\n  for (int i = 0; i < lines.size(); i++) {\n    if (is_line_contains_variable(lines[i])) {\n      env_vector.push_back(split_string(lines[i], '='));\n    }\n  }\n\n  for (int i = 0; i < env_vector.size(); i++) {\n#ifdef _WIN32\n    _putenv_s(env_vector[i][0].c_str(), env_vector[i][1].c_str());\n#else\n    setenv(env_vector[i][0].c_str(), env_vector[i][1].c_str(), 1);\n#endif\n  }\n}\n\nauto get_env_int(_In_ const char *pKey) -> int {\n  int value = -1;\n  if (const char *env_p = getenv(pKey)) {\n    std::string temp(env_p);\n    value = std::stoi(temp);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\nauto get_env_float(_In_ const char *pKey) -> float {\n  float value = -1;\n  if (const char *env_p = getenv(pKey)) {\n    std::string temp(env_p);\n    value = std::stof(temp);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\nauto get_env_boolean(_In_ const char *pKey) -> bool {\n  bool value = false;\n  if (const char *env_p = getenv(pKey)) {\n    std::string temp(env_p);\n    value = string_2_boolean(temp);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\nauto get_env_string(_In_ const char *pKey) -> std::string {\n  std::string value;\n  if (const char *env_p = getenv(pKey)) {\n    value = std::string(env_p);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\nauto get_env_cv_rect(_In_ const char *pKey) -> cv::Rect {\n  cv::Rect value = cv::Rect(0, 0, 0, 0);\n  if (const char *env_p = getenv(pKey)) {\n    std::string temp(env_p);\n    std::vector<int> int_vect =\n        line_of_numbers_in_string_to_vector_of_integers(temp);\n    value = cv::Rect(int_vect[0], int_vect[1], int_vect[2], int_vect[3]);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\nauto get_relative_path_to_root() -> std::string {\n  fs::path cwd = fs::current_path();\n  fs::path dot_env_file_path;\n  if (cwd.parent_path().filename().compare(\"build\") == 0) {\n    dot_env_file_path = \"../../\";\n  } else if (cwd.filename().compare(\"build\") == 0 ||\n             cwd.filename().compare(\"ocr\") == 0) {\n    dot_env_file_path = \"../\";\n  } else if (cwd.parent_path().parent_path().filename().compare(\"build\") == 0) {\n    dot_env_file_path = \"../../../\";\n  } else {\n    dot_env_file_path = \"\";\n  }\n\n  std::string temp = dot_env_file_path.string();\n\n  return temp;\n}\n\nauto get_first_character_of_string(_In_ std::string pStr, _In_ bool pEscape)\n    -> std::string {\n  if (pEscape || pStr.length() == 0) {\n    return pStr;\n  }\n\n  char first_char = pStr[0];\n  std::string result(1, first_char);\n\n  return result;\n}\n} // namespace wolf::ml::ocr\n"
  },
  {
    "path": "wolf/ml/referee_ocr/w_utilities.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <cstdlib>\n#include <fstream>\n#include <iostream>\n#include <map>\n#include <opencv2/opencv.hpp>\n#include <vector>\n\n#include \"w_referee.hpp\"\n#include \"wolf.hpp\"\n\nnamespace wolf::ml::ocr {\n\n/*!\n        The get_nearest_string returns the nearest string to input among strings\n   stored to the file specified by pFilePath environment variable. when the most\n   similar string is found, its similarity is compared to SIMILARITY_THRESHOLD\n   environment variable and if greater than it, the similar string is returned.\n   otherwise, the input string is returned.\n\n        \\param pInput The input string.\n        \\param pFilePath The file path contains target strings.\n        \\return The most similar string to input string.\n*/\nW_API auto get_nearest_string(_In_ std::string pInput,\n                              _In_ std::string pFilePath) -> std::string;\n\n/*!\n        return the nearest string to input among strings stored in the input\n   pMap. when the most similar string is found, its similarity is compared to\n   SIMILARITY_THRESHOLD environment variable and if greater than it, the similar\n   string is returned. otherwise, the input string is returned.\n\n        \\param pInput The input string.\n        \\param pMap A map contains the target strings.\n        \\return most similar string to input string.\n*/\nW_API auto get_nearest_string(_In_ std::string pInput,\n                              _In_ std::map<std::string, std::string> pMap)\n    -> std::string;\n\n/*!\n        The function gets the specific value by it's key and return the value in\n   string format.\n\n        \\param pJsonFilePath the path of json file.\n        \\param pKey the corresponding key that related to the desired value.\n        \\return desired value.\n*/\nW_API std::string get_value_from_json_file_by_key(std::string pJsonFilePath,\n                                                  std::string pKey);\n\n/*!\n        The function gets a string as input, the string contains numbers of int\n   numbers separated by spaces and split them and return them in a vector of\n   integers.\n\n        \\param pVariable string of integers number.\n        \\return a vector of integers.\n*/\nW_API std::vector<int>\nline_of_numbers_in_string_to_vector_of_integers(std::string pVariable);\n\n/*!\n        compute the normalized similarity between input strings using the\n   Levenshtein metric. output is a number between 0 and 1. 1 shows high\n   similarity and 0 shows low similarity.\n\n        \\param s1 first string.\n        \\param s2 second string.\n        \\return normalized similarity metric.\n*/\nW_API auto normalized_levenshtein_similarity(_In_ const std::string &s1,\n                                             _In_ const std::string &s2)\n    -> float;\n\n/*!\n        replace the specified phrase with another specified phrase in string.\n\n        \\param str input string.\n        \\param from first phrase.\n        \\param to second phrase.\n        \\return boolean parameter show success or failure of function\n*/\nW_API bool replace_string(std::string &str, const std::string &from,\n                          const std::string &to);\n\n/*!\n        The function gets a string as input and return the boolean\n   representation of the input.\n\n        \\param pVariable the string input.\n        \\return the boolean representain of the input string.\n*/\nW_API bool string_2_boolean(std::string pVariable);\n\n/*!\n        The function gets a string as input, the string contains numbers of int\n   numbers separated by spaces and split them and return them in a vector of\n   integers.\n\n        \\param pVideoResult The result of the video.\n        \\param pOutputImageFolderPath The path for the output image folder.\n        \\param pVideoPath The path of the game video.\n        \\return\n*/\nW_API auto store_image_in_folder(\n    _In_ std::vector<w_referee::match_result_struct> &pVideoResult,\n    _In_ std::string pOutputImageFolderPath, _In_ std::string pVideoPath)\n    -> void;\n\nW_API void write_in_file_append(std::string file_path, std::string content);\n\nW_API void write_in_file(std::string file_path, std::string content);\nW_API std::vector<std::string> split_string(std::string input_string,\n                                            char reference);\n\n/*!\n        The function stores the video output text result in the pOutputTextPath\n   file path.\n\n        \\param pVideoResult The result of the video.\n        \\param pOutputTextPath The path for the output text file.\n        \\return\n*/\nW_API auto write_results_in_file(\n    _In_ std::vector<w_referee::match_result_struct> &pVideoResult,\n    _In_ std::string pOutputTextPath) -> void;\n\n/*!\n        The function reads all lines of the input file and returns them in a\n   string vector.\n\n        \\param pFilePath The path of the input file.\n        \\return a vector of strings.\n*/\nW_API auto read_text_file_line_by_line(_In_ std::string pFilePath)\n    -> std::vector<std::string>;\n\n/*!\n        The .env file may have empty or commented lines. The\n   is_line_contains_variable functions use to detect these lines.\n\n        \\param pStr The input string.\n        \\return False, if the input string contains # or is empty.\n*/\nW_API auto is_line_contains_variable(const std::string pStr) -> bool;\n\n/*!\n        The function reads environment variables from the .env file and set them\n   in the environment by using the putenv function.\n\n        \\param pDotEnvFilePath The path of the .env file.\n        \\return\n*/\nW_API auto set_env(_In_ const char *pDotEnvFilePath) -> void;\n\n/*!\n        The function return the value of an environment variable based on the\n   input key.\n\n        \\param pKey The path of the .env file.\n        \\return the value of the variable in int.\n*/\nW_API auto get_env_int(_In_ const char *pKey) -> int;\n\n/*!\n        The function return the value of an environment variable based on the\n   input key.\n\n        \\param pKey The path of the .env file.\n        \\return the value of the variable in float.\n*/\nW_API auto get_env_float(_In_ const char *pKey) -> float;\n\n/*!\n        The function return the value of an environment variable based on the\n   input key.\n\n        \\param pKey The path of the .env file.\n        \\return the value of the variable in boolean.\n*/\nW_API auto get_env_boolean(_In_ const char *pKey) -> bool;\n\n/*!\n        The function return the value of an environment variable based on the\n   input key.\n\n        \\param pKey The path of the .env file.\n        \\return the value of the variable in string.\n*/\nW_API auto get_env_string(_In_ const char *pKey) -> std::string;\n\n/*!\n        The function return the value of an environment variable based on the\n   input key.\n\n        \\param pKey The path of the .env file.\n        \\return The value of the variable in cv::Rect.\n*/\nW_API auto get_env_cv_rect(_In_ const char *pKey) -> cv::Rect;\n\n/*!\n        The function returns the related root path compared to the current path.\n\n        \\return The related root path compared to the current path.\n*/\nW_API auto get_relative_path_to_root() -> std::string;\n\n/*!\n        The get_first_character_of_string function returns the first character\n   of the string.\n\n        \\param pStr The input string.\n        \\param pScape if true then return input string without any change.\n        \\return The first character of input string.\n*/\nW_API auto get_first_character_of_string(_In_ std::string pStr,\n                                         _In_ bool pEscape) -> std::string;\n} // namespace wolf::ml::ocr\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/soccer/.fill_stat_map",
    "content": "\nCONFIG_SIMILARITY_ALGORITHM=NormalizedLevenshtein\nCONFIG_USE_SIMILARITY=True\nSIMILAR_STRINGS_FILE_PATH=asset/team_names.txt\nSIMILARITY_THRESHOLD=0.5\nSOCCER_GLOBAL_HEIGHT_TO_DIST_RATIO=0.4\nSOCCER_GLOBAL_PLATFORM_FREE=TRUE\nSOCCER_NAME_AWAY_DO_RESIZE_CONTOUR=FALSE\nSOCCER_NAME_AWAY_GAUSSIAN_BLUR_WIN_SIZE=5\nSOCCER_NAME_AWAY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_NAME_AWAY_IS_DIGIT=FALSE\nSOCCER_NAME_AWAY_IS_TIME=FALSE\nSOCCER_NAME_AWAY_IS_WHITE=TRUE\nSOCCER_NAME_AWAY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_NAME_AWAY_MARGIN=5\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_AREA=1000\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_HEIGHT=100\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_WIDTH=100\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_AREA=1\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_WIDTH=1\nSOCCER_NAME_AWAY_THRESHOLD=150\nSOCCER_NAME_AWAY_VERBOSE=FALSE\nSOCCER_NAME_AWAY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_NAME_AWAY_WINDOW_NAME=name_away\nSOCCER_NAME_AWAY_WINDOW=740,103,337,42\nSOCCER_NAME_HOME_DO_RESIZE_CONTOUR=TRUE\nSOCCER_NAME_HOME_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_NAME_HOME_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_NAME_HOME_IS_DIGIT=FALSE\nSOCCER_NAME_HOME_IS_TIME=FALSE\nSOCCER_NAME_HOME_IS_WHITE=TRUE\nSOCCER_NAME_HOME_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_NAME_HOME_MARGIN=5\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_AREA=500\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_HEIGHT=40\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_WIDTH=30\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_AREA=1\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_WIDTH=1\nSOCCER_NAME_HOME_THRESHOLD=150\nSOCCER_NAME_HOME_VERBOSE=False\nSOCCER_NAME_HOME_WHITE_BACKGROUND_THRESHOLD=40\nSOCCER_NAME_HOME_WINDOW_NAME=name_home\nSOCCER_NAME_HOME_WINDOW=200,103,337,42\nSOCCER_RESULT_AWAY_DO_RESIZE_CONTOUR=FALSE\nSOCCER_RESULT_AWAY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_RESULT_AWAY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_RESULT_AWAY_IS_DIGIT=TRUE\nSOCCER_RESULT_AWAY_IS_TIME=TRUE\nSOCCER_RESULT_AWAY_IS_WHITE=TRUE\nSOCCER_RESULT_AWAY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_RESULT_AWAY_MARGIN=6\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_AREA=10000\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_WIDTH=32\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_AREA=20\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_WIDTH=4\nSOCCER_RESULT_AWAY_THRESHOLD=110\nSOCCER_RESULT_AWAY_VERBOSE=FALSE\nSOCCER_RESULT_AWAY_WHITE_BACKGROUND_THRESHOLD=150\nSOCCER_RESULT_AWAY_WINDOW_NAME=result_away\nSOCCER_RESULT_AWAY_WINDOW=685,99,32,47\nSOCCER_RESULT_HOME_DO_RESIZE_CONTOUR=FALSE\nSOCCER_RESULT_HOME_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_RESULT_HOME_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_RESULT_HOME_IS_DIGIT=TRUE\nSOCCER_RESULT_HOME_IS_TIME=TRUE\nSOCCER_RESULT_HOME_IS_WHITE=TRUE\nSOCCER_RESULT_HOME_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_RESULT_HOME_MARGIN=6\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_AREA=1500\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_WIDTH=32\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_AREA=20\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_WIDTH=4\nSOCCER_RESULT_HOME_THRESHOLD=110\nSOCCER_RESULT_HOME_VERBOSE=FALSE\nSOCCER_RESULT_HOME_WHITE_BACKGROUND_THRESHOLD=150\nSOCCER_RESULT_HOME_WINDOW_NAME=game_result_home\nSOCCER_RESULT_HOME_WINDOW=564,99,32,47\nSOCCER_SCREEN_IDENTITY_DO_RESIZE_CONTOUR=TRUE\nSOCCER_SCREEN_IDENTITY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_SCREEN_IDENTITY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_SCREEN_IDENTITY_IS_DIGIT=TRUE\nSOCCER_SCREEN_IDENTITY_IS_TIME=FALSE\nSOCCER_SCREEN_IDENTITY_IS_WHITE=TRUE\nSOCCER_SCREEN_IDENTITY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_SCREEN_IDENTITY_MARGIN=5\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_AREA=105\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_HEIGHT=16\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_WIDTH=14\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_AREA=2\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_HEIGHT=8\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_WIDTH=2\nSOCCER_SCREEN_IDENTITY_THRESHOLD=150\nSOCCER_SCREEN_IDENTITY_VERBOSE=FALSE\nSOCCER_SCREEN_IDENTITY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_SCREEN_IDENTITY_WINDOW_NAME=screen_identity\nSOCCER_SCREEN_IDENTITY_WINDOW=614,80,17,26\nSOCCER_STAT_EXTRA_FIRST_HALF_STRING=105 00\nSOCCER_STAT_EXTRA_SECOND_HALF_STRING=120 00\nSOCCER_STAT_FIRST_HALF_STRING=45 00\nSOCCER_STAT_PENALTY_STRING=penalty\nSOCCER_STAT_SECOND_HALF_STRING=90 00\nTELEMETRY_USE=OFF\nTESSERACT_LOG=tesseract.log\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/soccer/.initial_match_result_struct",
    "content": "CONFIG_SIMILARITY_ALGORITHM=NormalizedLevenshtein\nCONFIG_USE_SIMILARITY=True\nSIMILARITY_THRESHOLD=0.5\nSOCCER_NAME_AWAY_DO_RESIZE_CONTOUR=FALSE\nSOCCER_NAME_AWAY_GAUSSIAN_BLUR_WIN_SIZE=5\nSOCCER_NAME_AWAY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_NAME_AWAY_IS_DIGIT=FALSE\nSOCCER_NAME_AWAY_IS_TIME=FALSE\nSOCCER_NAME_AWAY_IS_WHITE=TRUE\nSOCCER_NAME_AWAY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_NAME_AWAY_MARGIN=5\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_AREA=1000\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_HEIGHT=100\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_WIDTH=100\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_AREA=1\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_WIDTH=1\nSOCCER_NAME_AWAY_THRESHOLD=150\nSOCCER_NAME_AWAY_VERBOSE=FALSE\nSOCCER_NAME_AWAY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_NAME_AWAY_WINDOW_NAME=name_away\nSOCCER_NAME_AWAY_WINDOW=740,103,337,42\nSOCCER_NAME_HOME_DO_RESIZE_CONTOUR=TRUE\nSOCCER_NAME_HOME_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_NAME_HOME_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_NAME_HOME_IS_DIGIT=FALSE\nSOCCER_NAME_HOME_IS_TIME=FALSE\nSOCCER_NAME_HOME_IS_WHITE=TRUE\nSOCCER_NAME_HOME_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_NAME_HOME_MARGIN=5\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_AREA=500\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_HEIGHT=40\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_WIDTH=30\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_AREA=1\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_WIDTH=1\nSOCCER_NAME_HOME_THRESHOLD=150\nSOCCER_NAME_HOME_VERBOSE=False\nSOCCER_NAME_HOME_WHITE_BACKGROUND_THRESHOLD=40\nSOCCER_NAME_HOME_WINDOW_NAME=name_home\nSOCCER_NAME_HOME_WINDOW=200,103,337,42\nSOCCER_RESULT_AWAY_DO_RESIZE_CONTOUR=FALSE\nSOCCER_RESULT_AWAY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_RESULT_AWAY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_RESULT_AWAY_IS_DIGIT=TRUE\nSOCCER_RESULT_AWAY_IS_TIME=TRUE\nSOCCER_RESULT_AWAY_IS_WHITE=TRUE\nSOCCER_RESULT_AWAY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_RESULT_AWAY_MARGIN=6\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_AREA=10000\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_WIDTH=32\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_AREA=20\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_WIDTH=4\nSOCCER_RESULT_AWAY_THRESHOLD=110\nSOCCER_RESULT_AWAY_VERBOSE=FALSE\nSOCCER_RESULT_AWAY_WHITE_BACKGROUND_THRESHOLD=150\nSOCCER_RESULT_AWAY_WINDOW_NAME=result_away\nSOCCER_RESULT_AWAY_WINDOW=685,99,32,47\nSOCCER_RESULT_HOME_DO_RESIZE_CONTOUR=FALSE\nSOCCER_RESULT_HOME_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_RESULT_HOME_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_RESULT_HOME_IS_DIGIT=TRUE\nSOCCER_RESULT_HOME_IS_TIME=TRUE\nSOCCER_RESULT_HOME_IS_WHITE=TRUE\nSOCCER_RESULT_HOME_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_RESULT_HOME_MARGIN=6\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_AREA=1500\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_WIDTH=32\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_AREA=20\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_WIDTH=4\nSOCCER_RESULT_HOME_THRESHOLD=110\nSOCCER_RESULT_HOME_VERBOSE=FALSE\nSOCCER_RESULT_HOME_WHITE_BACKGROUND_THRESHOLD=150\nSOCCER_RESULT_HOME_WINDOW_NAME=game_result_home\nSOCCER_RESULT_HOME_WINDOW=564,99,32,47\nSOCCER_SCREEN_IDENTITY_DO_RESIZE_CONTOUR=TRUE\nSOCCER_SCREEN_IDENTITY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_SCREEN_IDENTITY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_SCREEN_IDENTITY_IS_DIGIT=TRUE\nSOCCER_SCREEN_IDENTITY_IS_TIME=FALSE\nSOCCER_SCREEN_IDENTITY_IS_WHITE=TRUE\nSOCCER_SCREEN_IDENTITY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_SCREEN_IDENTITY_MARGIN=5\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_AREA=105\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_HEIGHT=16\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_WIDTH=14\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_AREA=2\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_HEIGHT=8\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_WIDTH=2\nSOCCER_SCREEN_IDENTITY_THRESHOLD=150\nSOCCER_SCREEN_IDENTITY_VERBOSE=FALSE\nSOCCER_SCREEN_IDENTITY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_SCREEN_IDENTITY_WINDOW_NAME=screen_identity\nSOCCER_SCREEN_IDENTITY_WINDOW=614,80,17,26\nTELEMETRY_USE=OFF\nTESSERACT_LOG=tesseract.log\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/soccer/.replace_team_names_with_most_similar_string",
    "content": "SIMILAR_STRINGS_FILE_PATH=../wolf/ml/test/common_test_asset/soccer/replace_team_names_with_most_similar_string.txt\nSIMILARITY_THRESHOLD=0.5\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/soccer/.replace_team_names_with_most_similar_string_0_9",
    "content": "SIMILAR_STRINGS_FILE_PATH=../wolf/ml/test/common_test_asset/soccer/replace_team_names_with_most_similar_string.txt\nSIMILARITY_THRESHOLD=0.9\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/soccer/.set_config",
    "content": "SOCCER_SCREEN_IDENTITY=COMMENT\nSOCCER_SCREEN_IDENTITY_WINDOW_NAME=window_name_test\nSOCCER_SCREEN_IDENTITY_IS_TIME=FALSE\nSOCCER_SCREEN_IDENTITY_WINDOW=614,80,17,26\nSOCCER_SCREEN_IDENTITY_DO_RESIZE_CONTOUR=TRUE\nSOCCER_SCREEN_IDENTITY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_SCREEN_IDENTITY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_SCREEN_IDENTITY_IS_WHITE=TRUE\nSOCCER_SCREEN_IDENTITY_IS_DIGIT=TRUE\nSOCCER_SCREEN_IDENTITY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_SCREEN_IDENTITY_MARGIN=5\nSOCCER_SCREEN_IDENTITY_THRESHOLD=150\nSOCCER_SCREEN_IDENTITY_VERBOSE=FALSE\nSOCCER_SCREEN_IDENTITY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_AREA=105\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_AREA=2\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_WIDTH=14\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_WIDTH=2\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_HEIGHT=16\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_HEIGHT=8\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/soccer/.single_image_result_extraction",
    "content": "\nCONFIG_SIMILARITY_ALGORITHM=NormalizedLevenshtein\nCONFIG_USE_SIMILARITY=True\nSIMILAR_STRINGS_FILE_PATH=asset/team_names.txt\nSIMILARITY_THRESHOLD=0.5\nSIMILARITY_THRESHOLD_STAT=0.7\nSIMILARITY_USE_FOR_TEAM_NAMES=FALSE\nSOCCER_GLOBAL_FRAME_HEIGHT=720\nSOCCER_GLOBAL_FRAME_WIDTH=1280\nSOCCER_GLOBAL_HEIGHT_TO_DIST_RATIO=0.4\nSOCCER_GLOBAL_MIN_FRAMES=4\nSOCCER_GLOBAL_PLATFORM_FREE=TRUE\nSOCCER_GLOBAL_THRESHOLD=190\nSOCCER_NAME_AWAY_DO_RESIZE_CONTOUR=FALSE\nSOCCER_NAME_AWAY_GAUSSIAN_BLUR_WIN_SIZE=5\nSOCCER_NAME_AWAY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_NAME_AWAY_IS_DIGIT=FALSE\nSOCCER_NAME_AWAY_IS_TIME=FALSE\nSOCCER_NAME_AWAY_IS_WHITE=TRUE\nSOCCER_NAME_AWAY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_NAME_AWAY_MARGIN=5\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_AREA=1000\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_HEIGHT=100\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_WIDTH=100\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_AREA=1\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_WIDTH=1\nSOCCER_NAME_AWAY_THRESHOLD=150\nSOCCER_NAME_AWAY_VERBOSE=FALSE\nSOCCER_NAME_AWAY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_NAME_AWAY_WINDOW_NAME=name_away\nSOCCER_NAME_AWAY_WINDOW=740,103,337,42\nSOCCER_NAME_HOME_DO_RESIZE_CONTOUR=TRUE\nSOCCER_NAME_HOME_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_NAME_HOME_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_NAME_HOME_IS_DIGIT=FALSE\nSOCCER_NAME_HOME_IS_TIME=FALSE\nSOCCER_NAME_HOME_IS_WHITE=TRUE\nSOCCER_NAME_HOME_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_NAME_HOME_MARGIN=5\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_AREA=500\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_HEIGHT=40\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_WIDTH=30\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_AREA=1\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_WIDTH=1\nSOCCER_NAME_HOME_THRESHOLD=150\nSOCCER_NAME_HOME_VERBOSE=False\nSOCCER_NAME_HOME_WHITE_BACKGROUND_THRESHOLD=40\nSOCCER_NAME_HOME_WINDOW_NAME=name_home\nSOCCER_NAME_HOME_WINDOW=200,103,337,42\nSOCCER_PENALTY_RESTRICTIONS_MAX_AREA=1400\nSOCCER_PENALTY_RESTRICTIONS_MAX_HEIGHT=50\nSOCCER_PENALTY_RESTRICTIONS_MAX_WIDTH=30\nSOCCER_PENALTY_RESTRICTIONS_MIN_AREA=10\nSOCCER_PENALTY_RESTRICTIONS_MIN_HEIGHT=10\nSOCCER_PENALTY_RESTRICTIONS_MIN_WIDTH=2\nSOCCER_PLATFORM_FREE_FRACTION=0.6\nSOCCER_PLATFORM_FREE_RESTRICTIONS_MAX_AREA=1000\nSOCCER_PLATFORM_FREE_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_PLATFORM_FREE_RESTRICTIONS_MAX_WIDTH=27\nSOCCER_PLATFORM_FREE_RESTRICTIONS_MIN_AREA=10\nSOCCER_PLATFORM_FREE_RESTRICTIONS_MIN_HEIGHT=14\nSOCCER_PLATFORM_FREE_RESTRICTIONS_MIN_WIDTH=2\nSOCCER_RESULT_AWAY_DO_RESIZE_CONTOUR=FALSE\nSOCCER_RESULT_AWAY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_RESULT_AWAY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_RESULT_AWAY_IS_DIGIT=TRUE\nSOCCER_RESULT_AWAY_IS_TIME=TRUE\nSOCCER_RESULT_AWAY_IS_WHITE=TRUE\nSOCCER_RESULT_AWAY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_RESULT_AWAY_MARGIN=6\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_AREA=10000\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_WIDTH=32\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_AREA=20\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_WIDTH=4\nSOCCER_RESULT_AWAY_THRESHOLD=110\nSOCCER_RESULT_AWAY_VERBOSE=FALSE\nSOCCER_RESULT_AWAY_WHITE_BACKGROUND_THRESHOLD=150\nSOCCER_RESULT_AWAY_WINDOW_NAME=result_away\nSOCCER_RESULT_AWAY_WINDOW=685,99,32,47\nSOCCER_RESULT_HOME_DO_RESIZE_CONTOUR=FALSE\nSOCCER_RESULT_HOME_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_RESULT_HOME_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_RESULT_HOME_IS_DIGIT=TRUE\nSOCCER_RESULT_HOME_IS_TIME=TRUE\nSOCCER_RESULT_HOME_IS_WHITE=TRUE\nSOCCER_RESULT_HOME_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_RESULT_HOME_MARGIN=6\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_AREA=1500\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_WIDTH=32\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_AREA=20\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_WIDTH=4\nSOCCER_RESULT_HOME_THRESHOLD=110\nSOCCER_RESULT_HOME_VERBOSE=FALSE\nSOCCER_RESULT_HOME_WHITE_BACKGROUND_THRESHOLD=150\nSOCCER_RESULT_HOME_WINDOW_NAME=game_result_home\nSOCCER_RESULT_HOME_WINDOW=564,99,32,47\nSOCCER_SCREEN_IDENTITY_DO_RESIZE_CONTOUR=TRUE\nSOCCER_SCREEN_IDENTITY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_SCREEN_IDENTITY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_SCREEN_IDENTITY_IS_DIGIT=TRUE\nSOCCER_SCREEN_IDENTITY_IS_TIME=FALSE\nSOCCER_SCREEN_IDENTITY_IS_WHITE=TRUE\nSOCCER_SCREEN_IDENTITY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_SCREEN_IDENTITY_MARGIN=5\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_AREA=105\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_HEIGHT=16\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_WIDTH=14\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_AREA=2\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_HEIGHT=8\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_WIDTH=2\nSOCCER_SCREEN_IDENTITY_THRESHOLD=150\nSOCCER_SCREEN_IDENTITY_VERBOSE=FALSE\nSOCCER_SCREEN_IDENTITY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_SCREEN_IDENTITY_WINDOW_NAME=screen_identity\nSOCCER_SCREEN_IDENTITY_WINDOW=614,80,17,26\nSOCCER_STAT_CHECK_PENALTY=PEN\nSOCCER_STAT_EXTRA_FIRST_HALF_STRING=105 00\nSOCCER_STAT_EXTRA_SECOND_HALF_STRING=120 00\nSOCCER_STAT_FIRST_HALF_STRING=45 00\nSOCCER_STAT_PENALTY_STRING=PEN\nSOCCER_STAT_SECOND_HALF_STRING=90 00\nTELEMETRY_USE=OFF\nTESSERACT_LOG=tesseract.log\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/soccer/.update_match_data",
    "content": "CONFIG_SIMILARITY_ALGORITHM=NormalizedLevenshtein\nCONFIG_USE_SIMILARITY=True\nSIMILARITY_THRESHOLD=0.5\nSOCCER_NAME_AWAY_DO_RESIZE_CONTOUR=FALSE\nSOCCER_NAME_AWAY_GAUSSIAN_BLUR_WIN_SIZE=5\nSOCCER_NAME_AWAY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_NAME_AWAY_IS_DIGIT=FALSE\nSOCCER_NAME_AWAY_IS_TIME=FALSE\nSOCCER_NAME_AWAY_IS_WHITE=TRUE\nSOCCER_NAME_AWAY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_NAME_AWAY_MARGIN=5\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_AREA=1000\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_HEIGHT=100\nSOCCER_NAME_AWAY_RESTRICTIONS_MAX_WIDTH=100\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_AREA=1\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_NAME_AWAY_RESTRICTIONS_MIN_WIDTH=1\nSOCCER_NAME_AWAY_THRESHOLD=150\nSOCCER_NAME_AWAY_VERBOSE=FALSE\nSOCCER_NAME_AWAY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_NAME_AWAY_WINDOW_NAME=name_away\nSOCCER_NAME_AWAY_WINDOW=740,103,337,42\nSOCCER_NAME_HOME_DO_RESIZE_CONTOUR=TRUE\nSOCCER_NAME_HOME_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_NAME_HOME_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_NAME_HOME_IS_DIGIT=FALSE\nSOCCER_NAME_HOME_IS_TIME=FALSE\nSOCCER_NAME_HOME_IS_WHITE=TRUE\nSOCCER_NAME_HOME_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_NAME_HOME_MARGIN=5\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_AREA=500\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_HEIGHT=40\nSOCCER_NAME_HOME_RESTRICTIONS_MAX_WIDTH=30\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_AREA=1\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_NAME_HOME_RESTRICTIONS_MIN_WIDTH=1\nSOCCER_NAME_HOME_THRESHOLD=150\nSOCCER_NAME_HOME_VERBOSE=False\nSOCCER_NAME_HOME_WHITE_BACKGROUND_THRESHOLD=40\nSOCCER_NAME_HOME_WINDOW_NAME=name_home\nSOCCER_NAME_HOME_WINDOW=200,103,337,42\nSOCCER_RESULT_AWAY_DO_RESIZE_CONTOUR=FALSE\nSOCCER_RESULT_AWAY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_RESULT_AWAY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_RESULT_AWAY_IS_DIGIT=TRUE\nSOCCER_RESULT_AWAY_IS_TIME=TRUE\nSOCCER_RESULT_AWAY_IS_WHITE=TRUE\nSOCCER_RESULT_AWAY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_RESULT_AWAY_MARGIN=6\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_AREA=10000\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_RESULT_AWAY_RESTRICTIONS_MAX_WIDTH=32\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_AREA=20\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_RESULT_AWAY_RESTRICTIONS_MIN_WIDTH=4\nSOCCER_RESULT_AWAY_THRESHOLD=110\nSOCCER_RESULT_AWAY_VERBOSE=FALSE\nSOCCER_RESULT_AWAY_WHITE_BACKGROUND_THRESHOLD=150\nSOCCER_RESULT_AWAY_WINDOW_NAME=result_away\nSOCCER_RESULT_AWAY_WINDOW=685,99,32,47\nSOCCER_RESULT_HOME_DO_RESIZE_CONTOUR=FALSE\nSOCCER_RESULT_HOME_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_RESULT_HOME_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_RESULT_HOME_IS_DIGIT=TRUE\nSOCCER_RESULT_HOME_IS_TIME=TRUE\nSOCCER_RESULT_HOME_IS_WHITE=TRUE\nSOCCER_RESULT_HOME_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_RESULT_HOME_MARGIN=6\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_AREA=1500\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_HEIGHT=45\nSOCCER_RESULT_HOME_RESTRICTIONS_MAX_WIDTH=32\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_AREA=20\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_HEIGHT=20\nSOCCER_RESULT_HOME_RESTRICTIONS_MIN_WIDTH=4\nSOCCER_RESULT_HOME_THRESHOLD=110\nSOCCER_RESULT_HOME_VERBOSE=FALSE\nSOCCER_RESULT_HOME_WHITE_BACKGROUND_THRESHOLD=150\nSOCCER_RESULT_HOME_WINDOW_NAME=game_result_home\nSOCCER_RESULT_HOME_WINDOW=564,99,32,47\nSOCCER_SCREEN_IDENTITY_DO_RESIZE_CONTOUR=TRUE\nSOCCER_SCREEN_IDENTITY_GAUSSIAN_BLUR_WIN_SIZE=3\nSOCCER_SCREEN_IDENTITY_IF_STORE_IMAGE_BOXES=FALSE\nSOCCER_SCREEN_IDENTITY_IS_DIGIT=TRUE\nSOCCER_SCREEN_IDENTITY_IS_TIME=FALSE\nSOCCER_SCREEN_IDENTITY_IS_WHITE=TRUE\nSOCCER_SCREEN_IDENTITY_MAKE_WHITE_BACKGROUND=FALSE\nSOCCER_SCREEN_IDENTITY_MARGIN=5\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_AREA=105\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_HEIGHT=16\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MAX_WIDTH=14\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_AREA=2\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_HEIGHT=8\nSOCCER_SCREEN_IDENTITY_RESTRICTIONS_MIN_WIDTH=2\nSOCCER_SCREEN_IDENTITY_THRESHOLD=150\nSOCCER_SCREEN_IDENTITY_VERBOSE=FALSE\nSOCCER_SCREEN_IDENTITY_WHITE_BACKGROUND_THRESHOLD=30\nSOCCER_SCREEN_IDENTITY_WINDOW_NAME=screen_identity\nSOCCER_SCREEN_IDENTITY_WINDOW=614,80,17,26\nTELEMETRY_USE=OFF\nTESSERACT_LOG=tesseract.log\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/soccer/replace_team_names_with_most_similar_string.txt",
    "content": "REAL MADRID\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/.get_env_boolean",
    "content": "\n# Variables for testing get_env_boolean functions\nBOOLEAN_VALUE=True\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/.get_env_cv_rect",
    "content": "\n# Variables for testing get_env_boolean functions\nCV_RECT_VALUE=313,110,72,14\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/.get_env_float",
    "content": "\n# Variables for testing get_env_float functions\nFLOAT_VALUE=4.5\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/.get_env_int",
    "content": "\n# Variables for testing get_env_int functions\nINT_VALUE=7\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/.get_env_string",
    "content": "\n# Variables for testing get_env_boolean functions\nSTRING_VALUE=this is a test!\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/.get_nearest_string_0_5",
    "content": "SIMILAR_STRINGS_FILE_PATH=../wolf/ml/test/common_test_asset/utilities/get_nearest_string.txt\nSIMILARITY_THRESHOLD=0.5\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/.get_nearest_string_0_9",
    "content": "SIMILAR_STRINGS_FILE_PATH=../wolf/ml/test/common_test_asset/utilities/get_nearest_string.txt\nSIMILARITY_THRESHOLD=0.9\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/.set_env",
    "content": "# This is a comment line\nV1=v1\nV2=v2\n# Another comment line\nV3=v3\nV4=v4\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/get_nearest_string.txt",
    "content": "test1\nhello\n"
  },
  {
    "path": "wolf/ml/test/common_test_asset/utilities/get_value_from_json_file_by_key.json",
    "content": "{\n    \"cpp-test-json\": \"ready\",\n    \"cpp-env-json\": \"OFF\"\n}\n"
  },
  {
    "path": "wolf/ml/test/w_image_processor_test.hpp",
    "content": "#ifdef WOLF_TEST\n\n#pragma once\n\n#ifdef WOLF_ML_OCR\n\n#define BOOST_TEST_MODULE ml_image_processor\n\n#include <ml/referee_ocr/w_image_processor.hpp>\n\n#include <boost/test/included/unit_test.hpp>\n#include <filesystem>\n#include <opencv2/opencv.hpp>\n\nnamespace fs = std::filesystem;\nfs::path image_processor_path = \"../wolf/ml/test/common_test_asset/image_processor\";\n\nusing namespace wolf::ml::ocr;\n\nBOOST_AUTO_TEST_CASE(prepare_image_for_contour_detection_with_default_arguments) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_path =\n      image_processor_path / \"prepare_image_for_contour_detection_default.png\";\n  cv::Mat desired_image_temp = cv::imread(desired_image_path.string());\n  cv::Mat desired_image;\n  cv::cvtColor(desired_image_temp, desired_image, cv::COLOR_BGR2GRAY);\n  config_for_ocr_struct config_for_ocr_struct;\n  cv::Mat processed_image =\n      prepare_image_for_contour_detection(source_image, config_for_ocr_struct);\n  cv::Mat diff = processed_image != desired_image;\n  BOOST_TEST(cv::countNonZero(diff) == 0);\n}\n\nBOOST_AUTO_TEST_CASE(negative_image_with_default_arguments) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_path =\n      image_processor_path / \"negative_image_default.png\";\n  cv::Mat desired_image = cv::imread(desired_image_path.string());\n  negative_image(source_image);\n  BOOST_TEST((sum(source_image != desired_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\nBOOST_AUTO_TEST_CASE(make_white_background_with_default_arguments) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_temp =\n      image_processor_path / \"make_white_background_default.png\";\n  cv::Mat desired_image = cv::imread(desired_image_temp.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.make_white_background = true;\n  make_contour_white_background(source_image, config_for_ocr_struct);\n  BOOST_TEST((sum(source_image != desired_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\nBOOST_AUTO_TEST_CASE(make_white_background_with_threshold_50) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_temp =\n      image_processor_path / \"make_white_background_50.png\";\n  cv::Mat desired_image = cv::imread(desired_image_temp.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.make_white_background = true;\n  config_for_ocr_struct.white_background_threshold = 50;\n  make_contour_white_background(source_image, config_for_ocr_struct);\n  BOOST_TEST((sum(source_image != desired_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\nBOOST_AUTO_TEST_CASE(find_all_contours_on_image_with_contours) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  cv::Mat filtered_image =\n      prepare_image_for_contour_detection(source_image, config_for_ocr_struct);\n  std::vector<std::vector<cv::Point>> contours =\n      find_all_countors(filtered_image);\n  BOOST_TEST(contours.size() == 475);\n}\n\nBOOST_AUTO_TEST_CASE(find_all_contours_on_image_without_contours) {\n  fs::path source_image_path =\n      image_processor_path / \"find_all_contours_solid_black.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  cv::Mat filtered_image =\n      prepare_image_for_contour_detection(source_image, config_for_ocr_struct);\n  std::vector<std::vector<cv::Point>> contours =\n      find_all_countors(filtered_image);\n  BOOST_TEST(contours.size() == 0);\n}\n\nBOOST_AUTO_TEST_CASE(resize_function_with_only_height_argument) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  resize_image(source_image, 40);\n  BOOST_TEST(source_image.rows == 40);\n}\n\nBOOST_AUTO_TEST_CASE(resize_function_with_only_width_argument) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  resize_image(source_image, -1, 60);\n  BOOST_TEST(source_image.cols == 60);\n}\n\nBOOST_AUTO_TEST_CASE(resize_function_without_argument) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  int cols = source_image.cols;\n  int rows = source_image.rows;\n  resize_image(source_image);\n  BOOST_TEST(source_image.cols == cols);\n  BOOST_TEST(source_image.rows == rows);\n}\n\nBOOST_AUTO_TEST_CASE(gaussian_filter_with_default_argument) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_path =\n      image_processor_path / \"gaussian_filter_default.png\";\n  cv::Mat desired_image = cv::imread(desired_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  gaussian_blur(source_image, config_for_ocr_struct);\n  BOOST_TEST((sum(source_image != desired_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\nBOOST_AUTO_TEST_CASE(gaussian_filter_with_win_size_7) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_path = image_processor_path / \"gaussian_filter_7.png\";\n  cv::Mat desired_image = cv::imread(desired_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.gaussian_blur_win_size = 7;\n  gaussian_blur(source_image, config_for_ocr_struct);\n  BOOST_TEST((sum(source_image != desired_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\nBOOST_AUTO_TEST_CASE(threshold_filter_with_default_argument) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_path =\n      image_processor_path / \"threshold_filter_default.png\";\n  cv::Mat desired_image_temp = cv::imread(desired_image_path.string());\n  cv::Mat desired_image;\n  cv::cvtColor(desired_image_temp, desired_image, cv::COLOR_BGR2GRAY);\n  config_for_ocr_struct config_for_ocr_struct;\n  threshold_image(source_image, config_for_ocr_struct);\n  cv::Mat diff = source_image != desired_image;\n  BOOST_TEST(cv::countNonZero(diff) == 0);\n}\n\nBOOST_AUTO_TEST_CASE(threshold_filter_with_threshold_value_180) {\n  fs::path source_image_path = image_processor_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_path =\n      image_processor_path / \"threshold_filter_180.png\";\n  cv::Mat desired_image_temp = cv::imread(desired_image_path.string());\n  cv::Mat desired_image;\n  cv::cvtColor(desired_image_temp, desired_image, cv::COLOR_BGR2GRAY);\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.threshold_value = 180;\n  threshold_image(source_image, config_for_ocr_struct);\n  cv::Mat diff = desired_image != desired_image;\n  BOOST_TEST(cv::countNonZero(diff) == 0);\n}\n\n#endif // WOLF_ML_OCR\n\n#endif // WOLF_TEST\n"
  },
  {
    "path": "wolf/ml/test/w_ocr_engine_test.hpp",
    "content": "#ifdef WOLF_TEST\n\n#pragma once\n\n#ifdef WOLF_ML_OCR\n\n#define BOOST_TEST_MODULE ml_ocr_engine\n\n#include <ml/referee_ocr/w_ocr_engine.hpp>\n\n#include <boost/test/included/unit_test.hpp>\n#include <filesystem>\n#include <opencv2/opencv.hpp>\n\n#include <ml/referee_ocr/w_image_processor.hpp>\n\nusing namespace wolf::ml::ocr;\n\nnamespace fs = std::filesystem;\nw_ocr_engine ocr_object;\nfs::path ocr_engine_asset_path = \"../wolf/ml/test/common_test_asset/ocr_engine\";\n\nBOOST_AUTO_TEST_CASE(check_if_overlapped_with_default_arguments_on_overlapped_rects) {\n  cv::Rect rect1(0, 0, 10, 10);\n  cv::Rect rect2(0, 0, 10, 10);\n  config_for_ocr_struct config_for_ocr_struct;\n  BOOST_TEST(ocr_object.check_if_overlapped(rect1, rect2, config_for_ocr_struct) ==\n        true);\n}\n\nBOOST_AUTO_TEST_CASE(check_if_overlapped_with_default_arguments_on_non_overlapped_rects) {\n  cv::Rect rect1(0, 0, 10, 10);\n  cv::Rect rect2(10, 10, 10, 10);\n  config_for_ocr_struct config_for_ocr_struct;\n  BOOST_TEST(ocr_object.check_if_overlapped(rect1, rect2, config_for_ocr_struct) ==\n        false);\n}\n\nBOOST_AUTO_TEST_CASE(check_if_overlapped_with_threshold_0_01) {\n  cv::Rect rect1(0, 0, 10, 10);\n  cv::Rect rect2(9, 9, 10, 10);\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.overlapped_threshold = 0.01;\n  BOOST_TEST(ocr_object.check_if_overlapped(rect1, rect2, config_for_ocr_struct) ==\n        false);\n}\n\nBOOST_AUTO_TEST_CASE(check_if_overlapped_with_threshold_0_009) {\n  cv::Rect rect1(0, 0, 10, 10);\n  cv::Rect rect2(9, 9, 10, 10);\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.overlapped_threshold = 0.009;\n  BOOST_TEST(ocr_object.check_if_overlapped(rect1, rect2, config_for_ocr_struct) ==\n        true);\n}\n\nBOOST_AUTO_TEST_CASE(contours_to_char_structs_with_default_arguments) {\n  fs::path desired_image_path =\n      ocr_engine_asset_path / \"contours_to_char_structs_default.png\";\n  cv::Mat desired_image_temp = cv::imread(desired_image_path.string());\n  cv::Mat desired_image;\n  cv::cvtColor(desired_image_temp, desired_image, cv::COLOR_BGR2GRAY);\n  std::vector<std::vector<cv::Point>> contours =\n      find_all_countors(desired_image);\n  std::vector<w_ocr_engine::characters_struct> characters =\n      ocr_object.contours_to_char_structs(contours);\n  BOOST_TEST(characters.size() == 475);\n}\n\nBOOST_AUTO_TEST_CASE(contours_to_char_structs_with_default_arguments_on_empty_contour_vector) {\n  fs::path desired_image_path =\n      ocr_engine_asset_path / \"contours_to_char_structs_Solid_black.png\";\n  cv::Mat desired_image_temp = cv::imread(desired_image_path.string());\n  cv::Mat desired_image;\n  cv::cvtColor(desired_image_temp, desired_image, cv::COLOR_BGR2GRAY);\n  std::vector<std::vector<cv::Point>> contours =\n      find_all_countors(desired_image);\n  std::vector<w_ocr_engine::characters_struct> characters =\n      ocr_object.contours_to_char_structs(contours);\n  BOOST_TEST(characters.size() == 0);\n}\n\nBOOST_AUTO_TEST_CASE(enhance_contour_image_for_modelwithdefaultarguments) {\n  fs::path source_image_path = ocr_engine_asset_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  cv::Mat processed_image = source_image.clone();\n  config_for_ocr_struct config_for_ocr_struct;\n  ocr_object.enhance_contour_image_for_model(processed_image,\n                                             config_for_ocr_struct);\n  BOOST_TEST((sum(source_image != processed_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\nBOOST_AUTO_TEST_CASE(enhance_contour_image_for_model_with_resize) {\n  fs::path source_image_path = ocr_engine_asset_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_path =\n      ocr_engine_asset_path / \"enhance_contour_image_for_model_resize.png\";\n  cv::Mat desired_image = cv::imread(desired_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.do_resize_contour = true;\n  ocr_object.enhance_contour_image_for_model(source_image,\n                                             config_for_ocr_struct);\n  BOOST_TEST((sum(source_image != desired_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\nBOOST_AUTO_TEST_CASE(enhance_contour_image_for_modelwithmake_white) {\n  fs::path source_image_path = ocr_engine_asset_path / \"test_image.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  fs::path desired_image_path =\n      ocr_engine_asset_path / \"enhance_contour_image_for_model_make_white.png\";\n  cv::Mat desired_image = cv::imread(desired_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.make_white_background = true;\n  ocr_object.enhance_contour_image_for_model(source_image,\n                                             config_for_ocr_struct);\n  BOOST_TEST((sum(source_image != desired_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\nBOOST_AUTO_TEST_CASE(euclidean_distance_with_two_non_overlapped_chars) {\n  w_ocr_engine::characters_struct char1;\n  w_ocr_engine::characters_struct char2;\n  char1.center.x = 1;\n  char1.center.y = 1;\n  char2.center.x = 1;\n  char2.center.y = 2;\n  double distance = ocr_object.euclidean_distance(char1, char2);\n  BOOST_TEST(distance == 1);\n}\n\nBOOST_AUTO_TEST_CASE(euclidean_distance_with_two_overlapped_chars) {\n  w_ocr_engine::characters_struct char1;\n  w_ocr_engine::characters_struct char2;\n  char1.center.x = 1;\n  char1.center.y = 1;\n  char2.center.x = 1;\n  char2.center.y = 1;\n  double distance = ocr_object.euclidean_distance(char1, char2);\n  BOOST_TEST(distance == 0);\n}\n\nBOOST_AUTO_TEST_CASE(euclidean_distance_with_two_empty_chars) {\n  w_ocr_engine::characters_struct char1;\n  w_ocr_engine::characters_struct char2;\n  double distance = ocr_object.euclidean_distance(char1, char2);\n  BOOST_TEST(distance == 0);\n}\n\nBOOST_AUTO_TEST_CASE(filter_chars_by_contour_size_without_restriction) {\n  fs::path source_image_path =\n      ocr_engine_asset_path / \"filter_chars_by_contour_size.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.restrictions.max_area = 99999999;\n  config_for_ocr_struct.restrictions.min_area = 1;\n  config_for_ocr_struct.restrictions.max_height = 99999999;\n  config_for_ocr_struct.restrictions.min_height = 1;\n  config_for_ocr_struct.restrictions.max_width = 99999999;\n  config_for_ocr_struct.restrictions.min_width = 1;\n  cv::Mat prepared =\n      prepare_image_for_contour_detection(source_image, config_for_ocr_struct);\n  std::vector<std::vector<cv::Point>> contours = find_all_countors(prepared);\n  std::vector<w_ocr_engine::characters_struct> characters =\n      ocr_object.contours_to_char_structs(contours);\n  std::vector<w_ocr_engine::characters_struct> filtered_characters =\n      ocr_object.filter_chars_by_contour_size(characters,\n                                              config_for_ocr_struct);\n  BOOST_TEST(filtered_characters.size() == 3);\n}\n\nBOOST_AUTO_TEST_CASE(filter_chars_by_contour_size_by_area_restriction) {\n  fs::path source_image_path =\n      ocr_engine_asset_path / \"filter_chars_by_contour_size.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.restrictions.max_area = 500000;\n  config_for_ocr_struct.restrictions.min_area = 1;\n  config_for_ocr_struct.restrictions.max_height = 99999999;\n  config_for_ocr_struct.restrictions.min_height = 1;\n  config_for_ocr_struct.restrictions.max_width = 99999999;\n  config_for_ocr_struct.restrictions.min_width = 1;\n  cv::Mat prepared =\n      prepare_image_for_contour_detection(source_image, config_for_ocr_struct);\n  std::vector<std::vector<cv::Point>> contours = find_all_countors(prepared);\n  std::vector<w_ocr_engine::characters_struct> characters =\n      ocr_object.contours_to_char_structs(contours);\n  std::vector<w_ocr_engine::characters_struct> filtered_characters =\n      ocr_object.filter_chars_by_contour_size(characters,\n                                              config_for_ocr_struct);\n  BOOST_TEST(filtered_characters.size() == 2);\n}\n\nBOOST_AUTO_TEST_CASE(filter_chars_by_contour_size_by_width_restriction) {\n  fs::path source_image_path =\n      ocr_engine_asset_path / \"filter_chars_by_contour_size.png\";\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.restrictions.max_area = 500000;\n  config_for_ocr_struct.restrictions.min_area = 1;\n  config_for_ocr_struct.restrictions.max_height = 99999999;\n  config_for_ocr_struct.restrictions.min_height = 1;\n  config_for_ocr_struct.restrictions.max_width = 300;\n  config_for_ocr_struct.restrictions.min_width = 1;\n  cv::Mat prepared =\n      prepare_image_for_contour_detection(source_image, config_for_ocr_struct);\n  std::vector<std::vector<cv::Point>> contours = find_all_countors(prepared);\n  std::vector<w_ocr_engine::characters_struct> characters =\n      ocr_object.contours_to_char_structs(contours);\n  std::vector<w_ocr_engine::characters_struct> filtered_characters =\n      ocr_object.filter_chars_by_contour_size(characters,\n                                              config_for_ocr_struct);\n  BOOST_TEST(filtered_characters.size() == 1);\n}\n\nBOOST_AUTO_TEST_CASE(merge_overlapped_contours_on_two_overlapped_contours) {\n  config_for_ocr_struct config_for_ocr_struct;\n  w_ocr_engine::characters_struct char1;\n  char1.bound_rect.x = 0;\n  char1.bound_rect.y = 0;\n  char1.bound_rect.width = 10;\n  char1.bound_rect.height = 10;\n  w_ocr_engine::characters_struct char2;\n  char2.bound_rect.x = 0;\n  char2.bound_rect.y = 0;\n  char2.bound_rect.width = 10;\n  char2.bound_rect.height = 10;\n  std::vector<w_ocr_engine::characters_struct> characters;\n  characters.push_back(char1);\n  characters.push_back(char2);\n  ocr_object.merge_overlapped_contours(characters, config_for_ocr_struct);\n  BOOST_TEST(characters.size() == 1);\n}\n\nBOOST_AUTO_TEST_CASE(merge_overlapped_contours_on_two_non_overlapped_contours) {\n  config_for_ocr_struct config_for_ocr_struct;\n  w_ocr_engine::characters_struct char1;\n  char1.bound_rect.x = 0;\n  char1.bound_rect.y = 0;\n  char1.bound_rect.width = 10;\n  char1.bound_rect.height = 10;\n  w_ocr_engine::characters_struct char2;\n  char2.bound_rect.x = 0;\n  char2.bound_rect.y = 10;\n  char2.bound_rect.width = 10;\n  char2.bound_rect.height = 10;\n  std::vector<w_ocr_engine::characters_struct> characters;\n  characters.push_back(char1);\n  characters.push_back(char2);\n  ocr_object.merge_overlapped_contours(characters, config_for_ocr_struct);\n  BOOST_TEST(characters.size() == 2);\n}\n\nBOOST_AUTO_TEST_CASE(mask_contour_works) {\n  fs::path contours_image_path =\n      ocr_engine_asset_path / \"filter_chars_by_contour_size.png\";\n  fs::path source_image_path = ocr_engine_asset_path / \"test_image.png\";\n  fs::path desired_image_path = ocr_engine_asset_path / \"mask_contour.png\";\n  cv::Mat contours_image = cv::imread(contours_image_path.string());\n  cv::Mat source_image = cv::imread(source_image_path.string());\n  cv::Mat desired_image = cv::imread(desired_image_path.string());\n  config_for_ocr_struct config_for_ocr_struct;\n  config_for_ocr_struct.restrictions.max_area = 500000;\n  cv::Mat prepared = prepare_image_for_contour_detection(contours_image,\n                                                         config_for_ocr_struct);\n  std::vector<std::vector<cv::Point>> contours = find_all_countors(prepared);\n  std::vector<w_ocr_engine::characters_struct> characters =\n      ocr_object.contours_to_char_structs(contours);\n  cv::Mat processed = ocr_object.mask_contour(source_image, characters[1]);\n  BOOST_TEST((sum(processed != desired_image) == cv::Scalar(0, 0, 0, 0)));\n}\n\n#endif // WOLF_ML_OCR\n\n#endif // WOLF_TEST\n"
  },
  {
    "path": "wolf/ml/test/w_referee_test.hpp",
    "content": "#ifdef WOLF_TEST\n\n#pragma once\n\n#ifdef WOLF_ML_OCR\n\n#define BOOST_TEST_MODULE ml_referee\n\n#include <ml/referee_ocr/w_referee.hpp>\n\n#include <boost/test/included/unit_test.hpp>\n#include <filesystem>\n#include <opencv2/opencv.hpp>\n\n#include <ml/referee_ocr/w_ocr_engine.hpp>\n\nnamespace fs = std::filesystem;\nfs::path w_referee_path = \"../wolf/ml/test/common_test_asset/w_referee\";\n\nusing namespace wolf::ml::ocr;\n\nBOOST_AUTO_TEST_CASE(concatenate_name_result_function) {\n  w_referee ocr_referee_object;\n\n  std::vector<w_ocr_engine::character_and_center> cluster_temp;\n\n  w_ocr_engine::character_and_center char_center_temp;\n  char_center_temp.text = \"T\";\n  char_center_temp.center = cv::Point(5, 20);\n  cluster_temp.push_back(char_center_temp);\n  char_center_temp.text = \"e\";\n  char_center_temp.center = cv::Point(10, 20);\n  cluster_temp.push_back(char_center_temp);\n  char_center_temp.text = \"s\";\n  char_center_temp.center = cv::Point(15, 20);\n  cluster_temp.push_back(char_center_temp);\n  char_center_temp.text = \"t\";\n  char_center_temp.center = cv::Point(20, 20);\n  cluster_temp.push_back(char_center_temp);\n\n  w_ocr_engine::character_and_center temp_result =\n      ocr_referee_object.concatenate_name_result(cluster_temp);\n\n  BOOST_TEST(temp_result.text.compare(\"T e s t\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(if_the_string_is_in_the_vector_function) {\n  w_referee ocr_referee_object;\n\n  std::vector<w_referee::vote_over_string_vector> vote_vector_temp;\n  w_referee::vote_over_string_vector vote_var_temp;\n  vote_var_temp.already_voted = false;\n  vote_var_temp.center = cv::Point(70, 77);\n  vote_var_temp.str = \"Test\";\n  vote_vector_temp.push_back(vote_var_temp);\n\n  w_ocr_engine::character_and_center char_temp;\n  char_temp.center = cv::Point(70, 77);\n  char_temp.text = \"Test\";\n\n  BOOST_TEST(ocr_referee_object.if_the_string_is_in_the_vector(char_temp,\n                                                            vote_vector_temp));\n}\n\nBOOST_AUTO_TEST_CASE(voting_over_results_and_names_function) {\n  w_referee ocr_referee_object;\n\n  std::vector<w_referee::frame_result_struct> all_results_temp;\n  w_referee::frame_result_struct frame_date_temp;\n\n  frame_date_temp.frame_number = 110;\n  frame_date_temp.away_name.text = \"ENGLAND\";\n  frame_date_temp.away_result.text = \"1\";\n  frame_date_temp.home_name.text = \"IRAN\";\n  frame_date_temp.home_result.text = \"2\";\n  frame_date_temp.stat = w_referee::final_result;\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  frame_date_temp.away_result.text = \"3\";\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n  all_results_temp.push_back(frame_date_temp);\n\n  w_referee::frame_result_struct frame_date_result;\n\n  ocr_referee_object.voting_over_results_and_names(frame_date_result,\n                                                   all_results_temp);\n\n  BOOST_TEST(frame_date_result.away_result.text.compare(\"1\") == 0);\n}\n\n#endif // WOLF_ML_OCR\n\n#endif // WOLF_TEST\n"
  },
  {
    "path": "wolf/ml/test/w_soccer_test.hpp",
    "content": "#ifdef WOLF_TEST\n\n#pragma once\n\n#ifdef WOLF_ML_OCR\n\n#define BOOST_TEST_MODULE ml_soccer\n\n#include <ml/referee_ocr/w_soccer.hpp>\n\n#include <boost/test/included/unit_test.hpp>\n#include <filesystem>\n#include <new>\n#include <opencv2/opencv.hpp>\n\n#include <ml/referee_ocr/w_ocr_engine.hpp>\n#include <ml/referee_ocr/w_read_video_frames.hpp>\n#include <ml/referee_ocr/w_referee.hpp>\n#include <ml/referee_ocr/w_utilities.hpp>\n\nnamespace fs = std::filesystem;\nfs::path soccer_asset_path = \"../wolf/ml/test/common_test_asset/soccer\";\n\nusing namespace wolf::ml::ocr;\n\nBOOST_AUTO_TEST_CASE(set_config_function) {\n  fs::path env_file_path = soccer_asset_path / \".set_config\";\n\n  set_env(env_file_path.string().c_str());\n\n  char *type = new char[50];\n  snprintf(type, 50, \"SOCCER_SCREEN_IDENTITY\");\n  w_ocr_engine::config_struct screen_identity = w_soccer::set_config(type);\n\n  delete[] type;\n\n  BOOST_TEST(!screen_identity.config_for_ocr.verbose);\n  BOOST_TEST(screen_identity.config_for_ocr.restrictions.max_area == 105);\n  BOOST_TEST(screen_identity.name.compare(\"window_name_test\") == 0);\n}\n\nstd::vector<w_referee::match_result_struct> video_result;\ntypedef void ocr_callback(char *, int, uint8_t *, int, int);\n\nvoid ocr_result(char *pResultBuffer, int pResultBufferSize,\n                uint8_t *pImageBuffer, int pImageWidth, int pImageHeight) {\n  w_referee::match_result_struct match_result_temp;\n  std::string temp(pResultBuffer);\n  std::vector<std::string> result_vec = split_string(temp, ',');\n\n  match_result_temp.stat = result_vec[0];\n  match_result_temp.home_name.text = result_vec[1];\n  match_result_temp.home_result.text = result_vec[2];\n  match_result_temp.away_name.text = result_vec[3];\n  match_result_temp.away_result.text = result_vec[4];\n\n  cv::Mat image = cv::Mat(pImageHeight, pImageWidth, CV_8UC3, pImageBuffer);\n\n  match_result_temp.result_image = image;\n  video_result.push_back(match_result_temp);\n}\n\nBOOST_AUTO_TEST_CASE(single_image_result_extraction_function) {\n  fs::path json_file_path =\n      soccer_asset_path / \".single_image_result_extraction\";\n  fs::path video_path =\n      soccer_asset_path / \"single_image_result_extraction.mp4\";\n\n  set_env(json_file_path.string().c_str());\n\n  ocr_callback *_callback = &ocr_result;\n\n  w_soccer *referee_obj = new w_soccer();\n\n  // This is an example of using the Project\n  w_read_video_frames player(video_path.string());\n  int number_of_frames = int(player.get_frame_amount());\n\n  cv::Mat frame;\n  for (int i = 0; i < number_of_frames; i++) {\n    frame = player.read_video_frame_by_frame();\n    if (frame.empty()) {\n      break;\n    }\n\n    char *res_str = new char[256];\n    referee_obj->single_image_result_extraction(frame.data, frame.rows,\n                                                frame.cols, _callback);\n  }\n  frame.release();\n\n  std::cout << \"Results: \" << video_result[0].stat << \" \"\n            << video_result[0].home_name.text << \" \"\n            << video_result[0].away_name.text << \" \"\n            << video_result[0].home_result.text << \" \"\n            << video_result[0].away_result.text << std::endl;\n\n  BOOST_TEST(video_result[0].stat.compare(\"90 00\") == 0);\n  BOOST_TEST(video_result[0].home_name.text.compare(\"ARSENAL\") == 0);\n  BOOST_TEST(video_result[0].away_name.text.compare(\"FC BAYERN\") == 0);\n  BOOST_TEST(video_result[0].home_result.text.compare(\"0\") == 0);\n  BOOST_TEST(video_result[0].away_result.text.compare(\"8\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(fill_stat_map_function) {\n  fs::path json_file_path = soccer_asset_path / \".fill_stat_map\";\n\n  set_env(json_file_path.string().c_str());\n\n  w_soccer referee_obj;\n\n  std::map<std::string, std::string> stat_map = referee_obj.get_stat_map();\n\n  BOOST_TEST(stat_map[\"45 00\"].compare(\"first_half\") == 0);\n  BOOST_TEST(stat_map[\"90 00\"].compare(\"second_half\") == 0);\n  // BOOST_TEST(referee_obj->stat_extra_first_half.compare(\"105 00\") == 0);\n  // BOOST_TEST(referee_obj->stat_extra_second_half.compare(\"120 00\") == 0);\n  // BOOST_TEST(referee_obj->stat_penalty.compare(\"penalty\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(replace_team_names_with_most_similar_string_finds_similar_team_to_REALMDRD) {\n  std::vector<w_referee::match_result_struct> results;\n  w_referee::match_result_struct result;\n\n  fs::path similar_strings_path =\n      soccer_asset_path / \".replace_team_names_with_most_similar_string\";\n\n  set_env(similar_strings_path.string().c_str());\n\n  result.away_name.text = \"REALMDRD\";\n  results.push_back(result);\n\n  w_soccer::replace_team_names_with_most_similar_string(results);\n\n  BOOST_TEST(results[0].away_name.text.compare(\"REAL MADRID\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(initial_match_result_struct_function) {\n  fs::path json_file_path = soccer_asset_path / \".initial_match_result_struct\";\n\n  set_env(json_file_path.string().c_str());\n\n  w_referee::frame_result_struct frame_data;\n  frame_data.away_name.text = \"IRAN\";\n  frame_data.away_result.text = \"3\";\n  frame_data.home_name.text = \"ENGLAND\";\n  frame_data.home_result.text = \"3\";\n  frame_data.frame_number = 114;\n  frame_data.stat = \"first_half\";\n  cv::Mat image = cv::Mat::zeros(50, 50, CV_8UC3);\n\n  w_soccer soccer_object;\n\n  w_referee::match_result_struct match_struct_temp;\n  match_struct_temp =\n      soccer_object.initial_match_result_struct(frame_data, image);\n\n  image.release();\n  BOOST_TEST(match_struct_temp.all_frames_results[0].away_name.text.compare(\n              \"IRAN\") == 0);\n  BOOST_TEST(match_struct_temp.stat.compare(\"first_half\") == 0);\n  BOOST_TEST(match_struct_temp.all_frames_results[0].away_result.text.compare(\n              \"3\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(update_match_data_function) {\n  fs::path json_file_path = soccer_asset_path / \".update_match_data\";\n\n  set_env(json_file_path.string().c_str());\n\n  w_referee::frame_result_struct frame_data;\n  frame_data.away_name.text = \"IRAN\";\n  frame_data.away_result.text = \"3\";\n  frame_data.home_name.text = \"ENGLAND\";\n  frame_data.home_result.text = \"3\";\n  frame_data.frame_number = 114;\n  frame_data.stat = \"first_half\";\n  cv::Mat image = cv::Mat::zeros(50, 50, CV_8UC3);\n\n  w_soccer soccer_object;\n\n  std::vector<w_referee::match_result_struct> match_data_temp;\n  match_data_temp = soccer_object.get_matches_data();\n  BOOST_TEST(match_data_temp.size() == 0);\n\n  soccer_object.update_match_data(frame_data, image);\n  frame_data.frame_number = 116;\n  soccer_object.update_match_data(frame_data, image);\n  frame_data.frame_number = 117;\n  soccer_object.update_match_data(frame_data, image);\n\n  match_data_temp = soccer_object.get_matches_data();\n  BOOST_TEST(match_data_temp.size() == 1);\n\n  frame_data.frame_number = 210;\n  soccer_object.update_match_data(frame_data, image);\n\n  match_data_temp = soccer_object.get_matches_data();\n  BOOST_TEST(match_data_temp.size() == 2);\n  BOOST_TEST(match_data_temp[1].all_frames_results[0].frame_number == 210);\n}\n\nBOOST_AUTO_TEST_CASE(get_matches_data_function) {\n  fs::path json_file_path = soccer_asset_path / \".update_match_data\";\n\n  set_env(json_file_path.string().c_str());\n\n  w_referee::frame_result_struct frame_data;\n  frame_data.away_name.text = \"IRAN\";\n  frame_data.away_result.text = \"3\";\n  frame_data.home_name.text = \"ENGLAND\";\n  frame_data.home_result.text = \"3\";\n  frame_data.frame_number = 114;\n  frame_data.stat = \"first_half\";\n  cv::Mat image = cv::Mat::zeros(50, 50, CV_8UC3);\n\n  w_soccer soccer_object;\n\n  std::vector<w_referee::match_result_struct> match_data_temp;\n  soccer_object.update_match_data(frame_data, image);\n  match_data_temp = soccer_object.get_matches_data();\n  BOOST_TEST(match_data_temp.size() == 1);\n  BOOST_TEST(match_data_temp[0].all_frames_results[0].frame_number == 114);\n}\n\nBOOST_AUTO_TEST_CASE(replace_team_names_with_most_similar_string_finds_similar_team_to_empty_string) {\n  std::vector<w_referee::match_result_struct> results;\n  w_referee::match_result_struct result;\n\n  fs::path similar_strings_path =\n      soccer_asset_path / \".replace_team_names_with_most_similar_string\";\n\n  set_env(similar_strings_path.string().c_str());\n\n  result.away_name.text = \"\";\n  results.push_back(result);\n\n  w_soccer::replace_team_names_with_most_similar_string(results);\n\n  BOOST_TEST(results[0].away_name.text.compare(\"\") == 0);\n}\n\n\n#endif // WOLF_ML_OCR\n\n#endif // WOLF_TEST"
  },
  {
    "path": "wolf/ml/test/w_utilities_test.hpp",
    "content": "#ifdef WOLF_TEST\n\n#pragma once\n\n#ifdef WOLF_ML_OCR\n\n#define BOOST_TEST_MODULE ml_utilities\n\n#include <ml/referee_ocr/w_utilities.hpp>\n\n#include <boost/test/included/unit_test.hpp>\n#include <filesystem>\n#include <opencv2/opencv.hpp>\n\nnamespace fs = std::filesystem;\nfs::path utilities_asset_path = \"../wolf/ml/test/common_test_asset/utilities\";\n\nusing namespace wolf::ml::ocr;\n\nBOOST_AUTO_TEST_CASE(get_value_from_json_file_by_key_gives_value_by_key) {\n  fs::path json_file_path =\n      utilities_asset_path / \"get_value_from_json_file_by_key.json\";\n  std::string key = \"cpp-test-json\";\n  std::string value =\n      get_value_from_json_file_by_key(json_file_path.string(), key);\n  BOOST_TEST(value.compare(\"ready\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(string_2_boolean_on_capitalized_characters) {\n  std::vector<std::string> list_string;\n  list_string.push_back(\"true\");\n  list_string.push_back(\"FalSe\");\n  bool temp;\n  temp = string_2_boolean(list_string[0]);\n  BOOST_TEST(temp);\n  temp = string_2_boolean(list_string[1]);\n  BOOST_TEST(!temp);\n}\n\nBOOST_AUTO_TEST_CASE(line_of_numbers_in_string_to_vector_of_integers_function) {\n  std::string temp = \"100,200,300,400\";\n  std::vector<int> integer_list =\n      line_of_numbers_in_string_to_vector_of_integers(temp);\n  BOOST_TEST(integer_list[0] == 100);\n  BOOST_TEST(integer_list[1] == 200);\n  BOOST_TEST(integer_list[2] == 300);\n  BOOST_TEST(integer_list[3] == 400);\n}\n\nBOOST_AUTO_TEST_CASE(store_image_in_folder_function) {\n  std::vector<w_referee::match_result_struct> temp_video_result;\n  w_referee::match_result_struct temp;\n  w_referee::frame_result_struct frame_result;\n\n  frame_result.home_name.text = \"Home\";\n  frame_result.home_result.text = \"2\";\n  frame_result.away_name.text = \"Away\";\n  frame_result.away_result.text = \"1\";\n  frame_result.frame_number = 3;\n  frame_result.stat = \"first_half\";\n  int height = 50;\n  int width = 50;\n  temp.result_image = cv::Mat::zeros(height, width, CV_8UC3);\n  temp.all_frames_results.push_back(frame_result);\n  temp_video_result.push_back(temp);\n\n  std::string output_folder_path = \".\";\n  fs::path temp_video_path = \"../test/123.mp4\";\n  store_image_in_folder(temp_video_result, output_folder_path,\n                        temp_video_path.string());\n\n  fs::path file_path = \"./123_0.png\";\n\n  bool is_file_exist = false;\n  if (std::filesystem::remove(file_path.string())) {\n    is_file_exist = true;\n  }\n  BOOST_TEST(is_file_exist);\n}\n\nBOOST_AUTO_TEST_CASE(write_results_in_file_function) {\n  std::vector<w_referee::match_result_struct> temp_video_result;\n  w_referee::match_result_struct temp;\n  w_referee::frame_result_struct frame_result;\n\n  frame_result.home_name.text = \"Home\";\n  frame_result.home_result.text = \"2\";\n  frame_result.away_name.text = \"Away\";\n  frame_result.away_result.text = \"1\";\n  frame_result.frame_number = 3;\n  frame_result.stat = \"first_half\";\n  int height = 50;\n  int width = 50;\n  temp.result_image = cv::Mat::zeros(height, width, CV_8UC3);\n  temp.all_frames_results.push_back(frame_result);\n  temp_video_result.push_back(temp);\n\n  fs::path temp_output_text_file = \"./test_write_results_in_file.txt\";\n\n  write_results_in_file(temp_video_result, temp_output_text_file.string());\n\n  std::vector<std::string> lines =\n      read_text_file_line_by_line(temp_output_text_file.string());\n\n  if (!std::filesystem::remove(temp_output_text_file.string())) {\n    BOOST_TEST(false);\n  }\n\n  BOOST_TEST(lines[0].compare(temp_video_result[0].stat + \",\" +\n                           temp_video_result[0].home_name.text + \",\" +\n                           temp_video_result[0].home_result.text + \",\" +\n                           temp_video_result[0].away_name.text + \",\" +\n                           temp_video_result[0].away_result.text + \",\" +\n                           std::to_string(temp_video_result[0].frame_number)) ==\n          0);\n}\n\nBOOST_AUTO_TEST_CASE(read_text_file_line_by_line_function) {\n  fs::path file_path = \"./test_read_text_file_line_by_line.txt\";\n  std::string content = \"This is a test!\";\n\n  write_in_file_append(file_path.string(), content);\n  std::vector<std::string> lines =\n      read_text_file_line_by_line(file_path.string());\n\n  if (!std::filesystem::remove(file_path.string())) {\n    BOOST_TEST(false);\n  }\n\n  BOOST_TEST(lines[0].compare(content) == 0);\n}\n\nBOOST_AUTO_TEST_CASE(normalized_levenshtein_similarity_on_one_empty_argument) {\n  float similarity = normalized_levenshtein_similarity(\"\", \"text\");\n  BOOST_TEST(similarity == 0);\n}\n\nBOOST_AUTO_TEST_CASE(normalized_levenshtein_similarity_on_two_empty_argument) {\n  float similarity = normalized_levenshtein_similarity(\"\", \"\");\n  BOOST_TEST(similarity == 0);\n}\n\nBOOST_AUTO_TEST_CASE(normalized_levenshtein_similarity_on_two_equal_string) {\n  float similarity = normalized_levenshtein_similarity(\"test\", \"test\");\n  BOOST_TEST(similarity == 1);\n}\n\nBOOST_AUTO_TEST_CASE(normalized_levenshtein_similarity_with_similarity_0_5_on_strings) {\n  float similarity = normalized_levenshtein_similarity(\"test\", \"mast\");\n  BOOST_TEST(similarity == 0.5);\n}\n\nBOOST_AUTO_TEST_CASE(normalized_levenshtein_similarity_on_same_numbers) {\n  float similarity = normalized_levenshtein_similarity(\"1234\", \"1234\");\n  BOOST_TEST(similarity == 1);\n}\n\nBOOST_AUTO_TEST_CASE(normalized_levenshtein_similarity_on_strings_with_different_length) {\n  float similarity = normalized_levenshtein_similarity(\"test\", \"tst\");\n  BOOST_TEST(similarity == 0.75);\n}\n\nBOOST_AUTO_TEST_CASE(get_nearest_string_with_threshold_0_5_returns_similar_string) {\n  fs::path similar_strings_path =\n      utilities_asset_path / \".get_nearest_string_0_5\";\n\n  set_env(similar_strings_path.string().c_str());\n\n  std::string path = get_env_string(\"SIMILAR_STRINGS_FILE_PATH\");\n  std::string output = get_nearest_string(\"tst1\", path);\n  BOOST_TEST(output.compare(\"test1\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(get_nearest_string_with_threshold_0_9_returns_input) {\n  fs::path similar_strings_path =\n      utilities_asset_path / \".get_nearest_string_0_9\";\n\n  set_env(similar_strings_path.string().c_str());\n\n  std::string path = get_env_string(\"SIMILAR_STRINGS_FILE_PATH\");\n  std::string output = get_nearest_string(\"tst1\", path);\n  BOOST_TEST(output.compare(\"tst1\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(get_nearest_string_on_empty_string_returns_empty_string) {\n  fs::path similar_strings_path =\n      utilities_asset_path / \".get_nearest_string_0_5\";\n\n  set_env(similar_strings_path.string().c_str());\n\n  std::string path = get_env_string(\"SIMILAR_STRINGS_FILE_PATH\");\n  std::string output = get_nearest_string(\"\", path);\n  BOOST_TEST(output.compare(\"\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(replace_string_first_phrase_exists_in_text) {\n  std::string text = \"hello hamed\";\n  replace_string(text, \"hamed\", \"bagher\");\n  BOOST_TEST(text.compare(\"hello bagher\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(replace_string_returns_text_if_first_phrase_not_exists_in_text) {\n  std::string text = \"hello hamed\";\n  replace_string(text, \"shahoo\", \"bagher\");\n  BOOST_TEST(text.compare(\"hello hamed\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(replace_string_returns_empty_text_if_input_text_was_empty) {\n  std::string text = \"\";\n  replace_string(text, \"shahoo\", \"bagher\");\n  BOOST_TEST(text.compare(\"\") == 0);\n}\n\nBOOST_AUTO_TEST_CASE(is_line_contains_variable_function_find_empty_line) {\n  const std::string content = \"\";\n\n  BOOST_TEST(!is_line_contains_variable(content));\n}\n\nBOOST_AUTO_TEST_CASE(is_line_contains_variable_function_find_line_started_by_sharp) {\n  const std::string content = \"# This is a commented line!\";\n\n  BOOST_TEST(!is_line_contains_variable(content));\n}\n\nBOOST_AUTO_TEST_CASE(set_env_function) {\n  fs::path dot_env_file_path = utilities_asset_path / \".set_env\";\n\n  set_env(dot_env_file_path.string().c_str());\n\n  if (const char *env_p1 = getenv(\"V1\")) {\n    std::string temp(env_p1);\n    BOOST_TEST(temp.compare(\"v1\") == 0);\n  }\n  if (const char *env_p2 = getenv(\"V2\")) {\n    std::string temp(env_p2);\n    BOOST_TEST(temp.compare(\"v2\") == 0);\n  }\n  if (const char *env_p3 = getenv(\"V3\")) {\n    std::string temp(env_p3);\n    BOOST_TEST(temp.compare(\"v3\") == 0);\n  }\n  if (const char *env_p4 = getenv(\"V4\")) {\n    std::string temp(env_p4);\n    BOOST_TEST(temp.compare(\"v4\") == 0);\n  }\n}\n\nBOOST_AUTO_TEST_CASE(get_env_int_function) {\n  fs::path dot_env_file_path = utilities_asset_path / \".get_env_int\";\n\n  set_env(dot_env_file_path.string().c_str());\n\n  std::string key = \"INT_VALUE\";\n  int value = get_env_int(key.c_str());\n\n  BOOST_TEST(value == 7);\n}\n\nBOOST_AUTO_TEST_CASE(get_env_float_function) {\n  fs::path dot_env_file_path = utilities_asset_path / \".get_env_float\";\n\n  set_env(dot_env_file_path.string().c_str());\n\n  std::string key = \"FLOAT_VALUE\";\n  float value = get_env_float(key.c_str());\n\n  BOOST_TEST(value == 4.5);\n}\n\nBOOST_AUTO_TEST_CASE(get_env_boolean_function) {\n  fs::path dot_env_file_path = utilities_asset_path / \".get_env_boolean\";\n\n  set_env(dot_env_file_path.string().c_str());\n\n  std::string key = \"BOOLEAN_VALUE\";\n  bool value = get_env_boolean(key.c_str());\n\n  BOOST_TEST(value);\n}\n\nBOOST_AUTO_TEST_CASE(get_env_string_function) {\n  fs::path dot_env_file_path = utilities_asset_path / \".get_env_string\";\n\n  set_env(dot_env_file_path.string().c_str());\n\n  std::string key = \"STRING_VALUE\";\n  std::string value = get_env_string(key.c_str());\n\n  BOOST_TEST(value.compare(\"this is a test! == 0\"));\n}\n\nBOOST_AUTO_TEST_CASE(get_env_cv_rect_function) {\n  fs::path dot_env_file_path = utilities_asset_path / \".get_env_cv_rect\";\n\n  set_env(dot_env_file_path.string().c_str());\n\n  std::string key = \"CV_RECT_VALUE\";\n  cv::Rect value = get_env_cv_rect(key.c_str());\n\n  BOOST_TEST(value.x == 313);\n  BOOST_TEST(value.y == 110);\n  BOOST_TEST(value.width == 72);\n  BOOST_TEST(value.height == 14);\n}\n\nBOOST_AUTO_TEST_CASE(get_relative_path_to_root_function) {\n  std::string temp = get_relative_path_to_root();\n\n  bool result = (temp.compare(\"../\") == 0 || temp.compare(\"../../../\") == 0);\n\n  BOOST_TEST(result);\n}\n\n#endif // WOLF_ML_OCR\n\n#endif // WOLF_TEST\n"
  },
  {
    "path": "wolf/ml/w_common.cpp",
    "content": "#include \"w_common.hpp\"\n\n#include <algorithm>\n#include <cctype>\n#include <cstdlib>\n#include <filesystem>\n#include <fstream>\n#include <iomanip>\n#include <iostream>\n#include <numeric>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include <opencv2/opencv.hpp>\n\nnamespace wolf::ml {\n\nauto write_in_file_append(_In_ std::string pFilePath, _In_ std::string pContent) -> void {\n  std::ofstream file;\n\n  file.open(pFilePath, std::ios_base::app);  // append instead of overwrite\n  file << pContent << std::endl;\n\n  file.close();\n}\n\nauto read_text_file_line_by_line(_In_ std::string pFilePath) -> std::vector<std::string> {\n  std::vector<std::string> lines;\n  std::string line;\n\n  std::ifstream input_file(pFilePath);\n  if (!input_file.is_open()) {\n    std::cerr << \"Could not open the file - '\" << pFilePath << \"'\" << std::endl;\n    return lines;\n  }\n\n  while (std::getline(input_file, line)) {\n    lines.push_back(line);\n  }\n\n  input_file.close();\n  return lines;\n}\n\nauto split_string(_In_ std::string input_string, _In_ char reference) -> std::vector<std::string> {\n  std::stringstream test(input_string);\n  std::string segment;\n  std::vector<std::string> seglist;\n\n  while (std::getline(test, segment, reference)) {\n    seglist.push_back(segment);\n  }\n\n  return seglist;\n}\n\nauto string_2_boolean(_In_ std::string pVariable) -> bool {\n  bool result;\n  std::transform(pVariable.begin(), pVariable.end(), pVariable.begin(), ::tolower);\n\n  if (pVariable.compare(\"true\") == 0 || pVariable.compare(\"false\") == 0) {\n    std::istringstream is(pVariable);\n    is >> std::boolalpha >> result;\n  } else {\n    throw std::runtime_error(\"Invalid input, the input must be 'true' or 'false' not \" + pVariable);\n  }\n\n  return result;\n}\n\nauto is_line_contains_variable(const std::string pStr) -> bool {\n  bool decision = false;\n  if (pStr.size() > 0) {\n    if (pStr.at(0) != '#' && pStr.size() > 2) {\n      decision = true;\n    }\n  }\n  return decision;\n}\n\nauto set_env(_In_ const char* pDotEnvFilePath) -> void {\n#ifdef __TELEMETRY\n  auto span = trace::Scope(get_tracer()->StartSpan(\"set_env\"));\n#endif\n  std::string env_file_path(pDotEnvFilePath);\n  auto lines = read_text_file_line_by_line(env_file_path);\n\n  std::vector<std::vector<std::string>> env_vector;\n  for (int i = 0; i < lines.size(); i++) {\n    if (is_line_contains_variable(lines[i])) {\n      env_vector.push_back(split_string(lines[i], '='));\n    }\n  }\n\n  for (int i = 0; i < env_vector.size(); i++) {\n#ifdef _WIN32\n    _putenv_s(env_vector[i][0].c_str(), env_vector[i][1].c_str());\n#else\n    setenv(env_vector[i][0].c_str(), env_vector[i][1].c_str(), 1);\n#endif\n  }\n}\n\nauto get_env_int(_In_ const char* pKey) -> int {\n  int value = -1;\n  if (const char* env_p = getenv(pKey)) {\n    std::string temp(env_p);\n    value = std::stoi(temp);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\nauto get_env_float(_In_ const char* pKey) -> float {\n  float value = -1;\n  if (const char* env_p = getenv(pKey)) {\n    std::string temp(env_p);\n    value = std::stof(temp);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\nauto get_env_boolean(_In_ const char* pKey) -> bool {\n  bool value = false;\n  if (const char* env_p = getenv(pKey)) {\n    std::string temp(env_p);\n    value = string_2_boolean(temp);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\nauto get_env_string(_In_ const char* pKey) -> std::string {\n  std::string value;\n  if (const char* env_p = getenv(pKey)) {\n    value = std::string(env_p);\n  } else {\n    // TODO add log\n  }\n\n  return value;\n}\n\n}  // namespace wolf::ml"
  },
  {
    "path": "wolf/ml/w_common.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <cstdlib>\n#include <fstream>\n#include <iostream>\n#include <map>\n#include <vector>\n\n// #include \"salieri.h\"\n\n#include \"wolf.hpp\"\n#include <opencv2/opencv.hpp>\n\nnamespace wolf::ml {\n\n/*!\n        The function appends the input as input content to the end of the text file.\n\n        \\param pFilePath the file path.\n        \\param pContent the input text content.\n        \\return (void)\n*/\nW_API auto write_in_file_append(_In_ std::string pFilePath, _In_ std::string pContent) -> void;\n\n/*!\n        The function gets a string as input and return the boolean representation of the input.\n\n        \\param pVariable the string input.\n        \\return the boolean representain of the input string.\n*/\nW_API auto string_2_boolean(_In_ std::string pVariable) -> bool;\n\nW_API auto split_string(_In_ std::string input_string, _In_ char reference)\n    -> std::vector<std::string>;\n\n/*!\n        The function reads all lines of the input file and returns them in a string vector.\n\n        \\param pFilePath The path of the input file.\n        \\return a vector of strings.\n*/\nW_API auto read_text_file_line_by_line(_In_ std::string pFilePath) -> std::vector<std::string>;\n\n/*!\n        The .env file may have empty or commented lines. The is_line_contains_variable functions\n        use to detect these lines.\n\n        \\param pStr The input string.\n        \\return False, if the input string contains # or is empty.\n*/\nW_API auto is_line_contains_variable(const std::string pStr) -> bool;\n\n/*!\n        The function reads environment variables from the .env file and set them in the environment\n        by using the putenv function.\n\n        \\param pDotEnvFilePath The path of the .env file.\n        \\return\n*/\nW_API auto set_env(_In_ const char* pDotEnvFilePath) -> void;\n\n/*!\n        The function return the value of an environment variable based on the input key.\n\n        \\param pKey The path of the .env file.\n        \\return the value of the variable in int.\n*/\nW_API auto get_env_int(_In_ const char* pKey) -> int;\n\n/*!\n        The function return the value of an environment variable based on the input key.\n\n        \\param pKey The path of the .env file.\n        \\return the value of the variable in float.\n*/\nW_API auto get_env_float(_In_ const char* pKey) -> float;\n\n/*!\n        The function return the value of an environment variable based on the input key.\n\n        \\param pKey The path of the .env file.\n        \\return the value of the variable in boolean.\n*/\nW_API auto get_env_boolean(_In_ const char* pKey) -> bool;\n\n/*!\n        The function return the value of an environment variable based on the input key.\n\n        \\param pKey The path of the .env file.\n        \\return the value of the variable in string.\n*/\nW_API auto get_env_string(_In_ const char* pKey) -> std::string;\n\n}  // namespace wolf::ml\n"
  },
  {
    "path": "wolf/protos/raft.proto",
    "content": "syntax = \"proto3\";\npackage wolf.raft;\n\nservice Raft {\n    rpc BootstrapClientStreaming(stream RaftBootstrapReq) returns (RaftBootstrapRes) {}\n    rpc Bootstrap (RaftBootstrapReq) returns (RaftBootstrapRes) {}\n    rpc BootstrapServerStreaming(RaftBootstrapReq) returns (stream RaftBootstrapRes) {}\n    rpc BootstrapBidirectionalStreaming(stream RaftBootstrapReq) returns (stream RaftBootstrapRes) {}\n\n}\n\n/*\n    Represents all error codes of services\n*/\nenum ErrorCode {\n    RAFT_UNDEFINED_ERROR = 0;\n    RAFT_BOOTSTRAP_FAILED = 1;\n}\n\n/*\n    The structure of the error response which is shared\n    between all rpc(s) of all services.\n*/\nmessage RaftErrorRes {\n    string msg_id = 1;\n    ErrorCode code = 2;\n    string msg = 3;\n}\n\n/*\n    messages for Bootstrap\n*/\nmessage RaftBootstrapReq {\n    string msg_id = 1;\n    uint64 number_of_nodes = 3;\n}\n\nmessage RaftBootstrapOkRes {\n    string msg_id = 1;\n}\n\nmessage RaftBootstrapRes {\n    oneof response {\n        RaftBootstrapOkRes ok_res = 1;\n        RaftErrorRes error_res = 2;\n    }\n}\n"
  },
  {
    "path": "wolf/stream/grpc/w_grpc_client.cpp",
    "content": "//#include \"w_grpc_client.hpp\""
  },
  {
    "path": "wolf/stream/grpc/w_grpc_client.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_STREAM_GRPC\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n#include <boost/asio/steady_timer.hpp>\n#include <grpcpp/create_channel.h>\n#include <boost/asio/detached.hpp>\n\n#include <grpcpp/channel.h>\n#include <boost/asio/bind_executor.hpp>\n#include <agrpc/asio_grpc.hpp>\n\n#include <boost/asio/experimental/awaitable_operators.hpp>\n\n#include <system/w_time.hpp>\n\nnamespace wolf::stream::rpc {\nclass w_grpc_client {\n public:\n  W_API w_grpc_client() noexcept = default;\n  W_API ~w_grpc_client() noexcept = default;\n\n  W_API boost::leaf::result<int> init(_In_ const std::string_view p_server_url,\n                                      _In_ const short p_port) noexcept {\n    if (p_server_url.empty()) {\n      return W_FAILURE(std::errc::invalid_argument, \"missing grpc server url endpoint\");\n    }\n\n    grpc::ChannelArguments _channel_args{};\n    _channel_args.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH,\n                         INT_MAX);  // Set the maximum message size to the maximum value allowed by\n                                    // a 32-bit signed integer\n    _channel_args.SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH,\n                         INT_MAX);  // Set the maximum message size to the maximum value allowed by\n                                    // a 32-bit signed integer\n\n    const auto _host = wolf::format(\"{}:{}\", p_server_url, p_port);\n    this->_channel =\n        grpc::CreateCustomChannel(_host, grpc::InsecureChannelCredentials(), _channel_args);\n\n    if (this->_channel == nullptr) {\n      return W_FAILURE(std::errc::operation_canceled,\n                       \"could not create channel to connect to grpc server\");\n    }\n\n    return 0;\n  }\n\n  //  template <auto PrepareAsync, typename Stub, typename Request, typename Response>\n  //  W_API boost::asio::awaitable<void> send_bidirectional(_In_ Request& request,\n  //                                                        _Inout_ Response& response) {\n  //    Stub stub{_channel};\n  //    grpc::ClientContext client_context;\n  //\n  //    std::unique_ptr<grpc::ClientAsyncReaderWriter<Request, Response>> reader_writer;\n  //    bool request_ok = co_await agrpc::request(PrepareAsync, stub, client_context,\n  //    reader_writer); if (!request_ok) {\n  //      // Channel is either permanently broken or transiently broken but with the fail-fast\n  //      option. co_return;\n  //    }\n  //\n  //    // Reads and writes can be performed simultaneously.\n  //    using namespace boost::asio::experimental::awaitable_operators;\n  //    auto [read_ok, write_ok] =\n  //        co_await (agrpc::read(reader_writer, response) && agrpc::write(reader_writer, request));\n  //\n  //    // Do not forget to signal that we are done writing before finishing.\n  //    co_await agrpc::writes_done(reader_writer);\n  //\n  //    grpc::Status status;\n  //    co_await agrpc::finish(reader_writer, status);\n  //  }\n  //\n  //  template <auto PrepareAsync, typename Stub, typename Request, typename Response>\n  //  W_API boost::asio::awaitable<void> send_stream(_In_ Request& request,\n  //                                                 _Inout_ Response& response) noexcept {\n  //    Stub stub{_channel};\n  //    grpc::ClientContext client_context;\n  //\n  //    std::unique_ptr<grpc::ClientAsyncWriter<Request>> writer;\n  //    bool request_ok = co_await agrpc::request(PrepareAsync, stub, client_context, writer,\n  //    response);\n  //\n  //    // Optionally read initial metadata first.\n  //    bool read_ok = co_await agrpc::read_initial_metadata(writer);\n  //\n  //    // Send a message.\n  //    bool write_ok = co_await agrpc::write(writer, request);\n  //\n  //    // Signal that we are done writing.\n  //    bool writes_done_ok = co_await agrpc::writes_done(writer);\n  //\n  //    // Wait for the server to recieve all our messages.\n  //    grpc::Status status;\n  //    co_await agrpc::finish(writer, status);\n  //\n  //    co_return;\n  //  }\n  \n  template <auto PrepareAsync, typename Stub, typename Request, typename Response>\n  W_API boost::asio::awaitable<void> send_unary(_In_ Request& p_request,\n                                                _Inout_ Response& p_response) noexcept {\n    Stub stub{_channel};\n    grpc::ClientContext client_context;\n\n    using RPC = agrpc::RPC<PrepareAsync>;\n    auto _res = co_await RPC::request(_context, stub, client_context, p_request, p_response,\n                                      boost::asio::use_awaitable);\n    co_return;\n  }\n  \n  template <class Function, typename... Args>\n  W_API void exec(_In_ std::chrono::steady_clock::duration&& p_timeout, _In_ Function&& p_function,\n                  _In_ Args&&... p_args) noexcept {\n    boost::asio::co_spawn(\n        this->_context,\n        [&]() -> boost::asio::template awaitable<void> {\n          co_await (std::forward<Function>(p_function)(std::forward<Args>(p_args)...) ||\n                    wolf::system::w_time::timeout(std::chrono::steady_clock::now() + p_timeout));\n        },\n        boost::asio::detached);\n\n    this->_context.run();\n  }\n\n private:\n  agrpc::GrpcContext _context;\n  std::shared_ptr<grpc::Channel> _channel;\n};\n}  // namespace wolf::stream::rpc\n\n#endif\n"
  },
  {
    "path": "wolf/stream/grpc/w_grpc_server.cpp",
    "content": "//#include \"w_grpc_server.hpp\"\n\n"
  },
  {
    "path": "wolf/stream/grpc/w_grpc_server.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_STREAM_GRPC\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n\n#include <agrpc/asio_grpc.hpp>\n#include <boost/asio/bind_executor.hpp>\n#include <boost/asio/co_spawn.hpp>\n#include <boost/asio/detached.hpp>\n#include <boost/asio/executor_work_guard.hpp>\n#include <boost/asio/experimental/awaitable_operators.hpp>\n#include <boost/asio/ip/tcp.hpp>\n#include <grpcpp/server.h>\n#include <grpcpp/server_builder.h>\n\nnamespace wolf::stream::rpc {\nclass w_grpc_server {\n public:\n  /*\n   * @param p_io_context, the boost io context\n   * @param p_url,the endpoint of the server\n   * @param p_port, the port of the server\n   * @param p_socket_options, the socket options\n   * @param p_on_data_callback, on data callback for session\n   * @param p_on_error_callback, on error callback for session\n   * @returns void\n   */\n  //W_API static boost::leaf::result<int> run(\n  //    _In_ boost::asio::io_context &p_io_context, _In_ const std::string_view &p_url,\n  //    _In_ const short p_port, _In_ std::chrono::steady_clock::duration &&p_timeout) noexcept;\n};\n}  // namespace wolf::stream::rpc\n\n#endif\n"
  },
  {
    "path": "wolf/stream/http/w_http_server.cpp",
    "content": "#include \"w_http_server.hpp\"\n#include <cstdio>\n\nusing w_http_server = wolf::stream::http::w_http_server;\n\nint log_message(const struct mg_connection *p_conn, const char *p_message)\n{\n  (void)p_conn;\n  std::fprintf(stderr, \"%s\\n\", p_message);\n  return 0;\n}\n\nstatic CivetCallbacks s_callbacks;\nconst CivetCallbacks *get_civet_callbacks()\n{\n  std::memset(&s_callbacks, 0, sizeof(s_callbacks));\n  s_callbacks.log_message = &log_message;\n  return &s_callbacks;\n}\n\nw_http_server::w_http_server(const std::vector<std::string> &p_options,\n                             const void *p_user_data)\n    : _server(std::make_unique<CivetServer>(p_options, get_civet_callbacks(),\n                                            p_user_data)) {}"
  },
  {
    "path": "wolf/stream/http/w_http_server.hpp",
    "content": "#pragma once\n\n#include <CivetServer.h>\n#include <functional>\n#include <json/json.h>\n#include <map>\n#include <memory>\n#include <string>\n#include <vector>\n\nnamespace wolf::stream::http\n{\n  using w_http_function =\n      std::function<std::pair<std::map<std::string, std::string>, Json::Value>(\n          const mg_request_info *req_info, const Json::Value &)>;\n\n  class w_http_server\n  {\n  public:\n    w_http_server(const std::vector<std::string> &p_options,\n                  const void *p_user_data);\n    virtual ~w_http_server(){};\n\n    // prevent copy constructor\n    w_http_server(const w_http_server &) = delete;\n\n    // prevent copying\n    w_http_server &operator=(const w_http_server &) = delete;\n\n    // void add_handlers(std::map<std::string, w_http_function> &p_funcs);\n    // void remove_handler(std::string p_handler_name);\n\n  private:\n    std::unique_ptr<CivetServer> _server;\n  };\n} // namespace wolf::stream::http\n"
  },
  {
    "path": "wolf/stream/janus/w_janus_api_emc.cpp",
    "content": "#if defined(WOLF_STREAM_JANUS) && defined(EMSCRIPTEN)\n\n#include \"w_janus_api_emc.hpp\"\n#include <cstdio>\n#include <emscripten/emscripten.h>\n\nusing w_janus_api_emc = wolf::stream::janus::w_janus_api_emc;\n\nstatic std::function<void(int)> s_on_init_callback = nullptr;\nstatic std::function<void(double)> s_on_screen_shared_callback = nullptr;\nstatic std::function<void(void)> s_on_join_room_callback = nullptr;\n\nextern \"C\" {\nEMSCRIPTEN_KEEPALIVE\nvoid on_init_callback(int p_init_state) {\n  if (s_on_init_callback) {\n    s_on_init_callback(p_init_state);\n  }\n}\n\nEMSCRIPTEN_KEEPALIVE\nvoid on_screen_shared(_In_ double p_room_id) {\n  if (s_on_screen_shared_callback) {\n    s_on_screen_shared_callback(p_room_id);\n  }\n}\n\nEMSCRIPTEN_KEEPALIVE\nvoid on_join_room_callback() {\n  if (s_on_join_room_callback) {\n    s_on_join_room_callback();\n  }\n}\n}\n\n// clang-format off\n\nboost::leaf::result<int>\nw_janus_api_emc::init(_In_ bool p_debug_mode,\n                      _In_ std::function<void(int)> p_on_init_callback) noexcept {\n\n  s_on_init_callback = std::move(p_on_init_callback);\n\n  return EM_ASM_INT({\n    var _debug = \"\";\n    \n    if ($0 === 1) {\n      _debug = \"all\";\n    }\n    // init Janus\n    Janus.init({\n      debug: _debug , callback: function () {\n        // Make sure the browser supports WebRTC\n        if (!Janus.isWebrtcSupported()) {\n          console.error(\"No WebRTC support\");\n          return 1;\n        }\n      }\n    });\n\n    // global variables\n    capture = null;\n    id = null;\n    local_tracks = {};\n    local_videos = 0;\n    remote_tracks = {};\n    remote_videos = 0;\n    role = null;\n    room = null;\n    screen = null;\n    source = null;\n    spinner = null;\n\n    // generate random opaque id\n    var _char_set = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\t  opaque_id = \"\";\n\t  for (var i = 0; i < 11; i++) {\n\t\t  var _random_pos = Math.floor(Math.random() * _char_set.length);\n\t\t  opaque_id += _char_set.substring(_random_pos, _random_pos + 1);\n\t  }\n\n    \n    // create a session\n\t\tjanus = new Janus({\n\t\t\t\tserver: server,\n\t\t\t\ticeServers: ice_servers,\n\t\t\t\tsuccess: function () {\n\t\t\t\t\t// attach to videoroom plugin\n\t\t\t\t\tjanus.attach(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tplugin: \"janus.plugin.videoroom\",\n\t\t\t\t\t\t\topaqueId: opaque_id,\n\t\t\t\t\t\t\tsuccess: function (p_plugin_handle) {\n\t\t\t\t\t\t\t\tscreen = p_plugin_handle;\n\t\t\t\t\t\t\t\tJanus.log(\"plugin attached! (\" + screen.getPlugin() + \", id=\" + screen.getId() + \")\");\n\t\t\t\t\t\t\t\t_on_init_callback(0);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terror: function (p_error) {\n\t\t\t\t\t\t\t\tJanus.error(\"error attaching plugin: \", p_error);\n\t\t\t\t\t\t\t\t_on_init_callback(1);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tconsentDialog: function (p_on) {\n\t\t\t\t\t\t\t\tJanus.debug(\"consent dialog should be \" + (p_on ? \"on\" : \"off\") + \" now\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ticeState: function (p_state) {\n\t\t\t\t\t\t\t\tJanus.log(\"ICE state changed to \" + p_state);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmediaState: function (p_medium, p_on, p_mid) {\n\t\t\t\t\t\t\t\tJanus.log(\"Janus \" + (p_on ? \"started\" : \"stopped\") + \" receiving our \" + p_medium + \" (mid=\" + p_mid + \")\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twebrtcState: function (p_on) {\n\t\t\t\t\t\t\t\tJanus.log(\"Janus WebRTC peer connection is \" + (p_on ? \"up\" : \"down\") + \" now\");\n\t\t\t\t\t\t\t\t$(\"#streamscreen\").parent().parent().unblock();\n\t\t\t\t\t\t\t\tif (p_on) {\n\t\t\t\t\t\t\t\t\tJanus.log(\"your screen sharing session just started: pass the \\\"\" + room + \"\\\" session identifier to those who want to attend.\");\n\t\t\t\t\t\t\t\t\t_on_screen_shared(room);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tJanus.log(\"your screen sharing session just stopped\");\n\t\t\t\t\t\t\t\t\tjanus.destroy();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tslowLink: function (p_uplink, p_lost, p_mid) {\n\t\t\t\t\t\t\t\tJanus.log(\"Janus reports problems \" + (p_uplink ? \"sending\" : \"receiving\") + \" packets on mid \" + p_mid + \" (\" + p_lost + \" lost packets)\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonmessage: function (p_msg, p_jsep) {\n\t\t\t\t\t\t\t\tJanus.debug(\"got a message (publisher): \", p_msg);\n\t\t\t\t\t\t\t\tvar _event = p_msg[\"videoroom\"];\n\t\t\t\t\t\t\t\tJanus.debug(\"event: \" + _event);\n\t\t\t\t\t\t\t\tif (_event) {\n\t\t\t\t\t\t\t\t\tif (_event === \"joined\") {\n\t\t\t\t\t\t\t\t\t\tid = p_msg[\"id\"];\n\t\t\t\t\t\t\t\t\t\tJanus.log(\"successfully joined room \" + p_msg[\"room\"] + \" with ID \" + id);\n\t\t\t\t\t\t\t\t\t\tif (role === \"publisher\") {\n\t\t\t\t\t\t\t\t\t\t\t// this is our session, publish our stream\n\t\t\t\t\t\t\t\t\t\t\tJanus.debug(\"negotiating WebRTC stream for our screen (capture \" + capture + \")\");\n\t\t\t\t\t\t\t\t\t\t\t// safari expects a user gesture to share the screen\n\t\t\t\t\t\t\t\t\t\t\tif (Janus.webRTCAdapter.browserDetails.browser === \"safari\") {\n\t\t\t\t\t\t\t\t\t\t\t\twindow.alert(\"Safari requires a user gesture before the screen can be shared: close this dialog to do that\");\n\t\t\t\t\t\t\t\t\t\t\t\tscreen.createOffer(\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// we want to capture the screen and audio, but sendonly\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttracks: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ type: 'audio', capture: true, recv: false },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ type: 'screen', capture: true, recv: false }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsuccess: function (p_jsep) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tJanus.debug(\"Got publisher SDP!\", p_jsep);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar _publish = { request: \"configure\", audio: true, video: true };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tscreen.send({ message: _publish, jsep: p_jsep });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\terror: function (p_error) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tJanus.error(\"WebRTC error:\", p_error.message);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t// other browsers should be fine, we try to call getDisplayMedia directly\n\t\t\t\t\t\t\t\t\t\t\t\tscreen.createOffer(\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// we want sendonly audio and screensharing\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttracks: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ type: 'audio', capture: true, recv: false },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ type: 'screen', capture: true, recv: false }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsuccess: function (p_jsep) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tJanus.debug(\"got publisher SDP!\", p_jsep);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar _publish = { request: \"configure\", audio: true, video: true };\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tscreen.send({ message: _publish, jsep: p_jsep });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\terror: function (p_error) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tJanus.error(\"WebRTC error:\", p_error);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t// we're just watching a session, any feed to attach to?\n\t\t\t\t\t\t\t\t\t\t\tif (p_msg[\"publishers\"]) {\n\t\t\t\t\t\t\t\t\t\t\t\tvar _list = p_msg[\"publishers\"];\n\t\t\t\t\t\t\t\t\t\t\t\tJanus.debug(\"got a list of available publishers/feeds:\", _list);\n\t\t\t\t\t\t\t\t\t\t\t\tfor (var f in _list) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (_list[f][\"dummy\"]) continue;\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar _id = _list[f][\"id\"];\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar _display = _list[f][\"display\"];\n\t\t\t\t\t\t\t\t\t\t\t\t\tJanus.debug(\"  >> [\" + _id + \"] \" + _display);\n\t\t\t\t\t\t\t\t\t\t\t\t\tnew_remote_feed(_id, _display)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else if (_event === \"event\") {\n\t\t\t\t\t\t\t\t\t\t// any feed to attach to?\n\t\t\t\t\t\t\t\t\t\tif (role === \"listener\" && p_msg[\"publishers\"]) {\n\t\t\t\t\t\t\t\t\t\t\tvar _list = p_msg[\"publishers\"];\n\t\t\t\t\t\t\t\t\t\t\tJanus.debug(\"got a list of available publishers/feeds:\", _list);\n\t\t\t\t\t\t\t\t\t\t\tfor (var f in _list) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (_list[f][\"dummy\"]) continue;\n\t\t\t\t\t\t\t\t\t\t\t\tvar _id = _list[f][\"id\"];\n\t\t\t\t\t\t\t\t\t\t\t\tvar _display = _list[f][\"display\"];\n\t\t\t\t\t\t\t\t\t\t\t\tJanus.debug(\"  >> [\" + _id + \"] \" + _display);\n\t\t\t\t\t\t\t\t\t\t\t\tnew_remote_feed(_id, _display)\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} else if (p_msg[\"leaving\"]) {\n\t\t\t\t\t\t\t\t\t\t\t// one of the publishers has gone away?\n\t\t\t\t\t\t\t\t\t\t\tvar _leaving = p_msg[\"leaving\"];\n\t\t\t\t\t\t\t\t\t\t\tJanus.log(\"publisher left: \" + _leaving);\n\t\t\t\t\t\t\t\t\t\t\tif (role === \"listener\" && p_msg[\"leaving\"] === source) {\n\t\t\t\t\t\t\t\t\t\t\t\tJanus.error(\"the screen sharing session is over, the publisher left\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} else if (p_msg[\"error\"]) {\n\t\t\t\t\t\t\t\t\t\t\tJanus.error(p_msg[\"error\"]);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (p_jsep) {\n\t\t\t\t\t\t\t\t\tJanus.debug(\"handling SDP as well \", p_jsep);\n\t\t\t\t\t\t\t\t\tscreen.handleRemoteJsep({ jsep: p_jsep });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonlocaltrack: function (p_track, p_on) {\n\t\t\t\t\t\t\t\tJanus.debug(\"local track \" + (p_on ? \"added\" : \"removed\") + \":\", p_track);\n\t\t\t\t\t\t\t\t// we use the track ID as name of the element, but it may contain invalid characters\n\t\t\t\t\t\t\t\tvar _track_id = p_track.id.replace(/[{}]/g, \"\");\n\t\t\t\t\t\t\t\tif (!p_on) {\n\t\t\t\t\t\t\t\t\t// track removed, get rid of the stream and the rendering\n\t\t\t\t\t\t\t\t\tvar _stream = local_tracks[_track_id];\n\t\t\t\t\t\t\t\t\tif (_stream) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tvar _tracks = _stream.getTracks();\n\t\t\t\t\t\t\t\t\t\t\tfor (var _t in _tracks) {\n\t\t\t\t\t\t\t\t\t\t\t\tvar _mst = _tracks[_t];\n\t\t\t\t\t\t\t\t\t\t\t\tif (_mst) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t_mst.stop();\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} catch (p_e) { }\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (p_track.kind === \"video\") {\n\t\t\t\t\t\t\t\t\t\t$('#screenvideo' + _track_id).remove();\n\t\t\t\t\t\t\t\t\t\tlocal_videos--;\n\t\t\t\t\t\t\t\t\t\tif (local_videos === 0) {\n\t\t\t\t\t\t\t\t\t\t\t// No video, at least for now: show a placeholder\n\t\t\t\t\t\t\t\t\t\t\tif ($('#streamscreen .no-video-container').length === 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tJanus.log(\"No webcam available\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdelete local_tracks[_track_id];\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// if we're here, a new track was added\n\t\t\t\t\t\t\t\tvar _stream = local_tracks[_track_id];\n\t\t\t\t\t\t\t\tif (_stream) {\n\t\t\t\t\t\t\t\t\t// we've been here already\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (p_track.kind === \"audio\") {\n\t\t\t\t\t\t\t\t\t// we ignore local audio tracks, they'd generate echo anyway\n\t\t\t\t\t\t\t\t\tif (local_videos === 0) {\n\t\t\t\t\t\t\t\t\t\t// No video, at least for now: show a placeholder\n\t\t\t\t\t\t\t\t\t\tif ($('#streamscreen .no-video-container').length === 0) {\n\t\t\t\t\t\t\t\t\t\t\tJanus.log(\"No webcam available\");\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// new video track: create a stream out of it\n\t\t\t\t\t\t\t\t\tlocal_videos++;\n\t\t\t\t\t\t\t\t\t$('#streamscreen .no-video-container').remove();\n\t\t\t\t\t\t\t\t\t_stream = new MediaStream([p_track]);\n\t\t\t\t\t\t\t\t\tlocal_tracks[_track_id] = _stream;\n\t\t\t\t\t\t\t\t\tJanus.log(\"Created local stream:\", _stream);\n\t\t\t\t\t\t\t\t\t$('#streamscreen').append('<video muted=\"muted\" id=\"screenvideo' + _track_id + '\" width=100% autoplay playsinline muted=\"muted\"/>');\n\t\t\t\t\t\t\t\t\tJanus.attachMediaStream($('#screenvideo' + _track_id).get(0), _stream);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (screen.webrtcStuff.pc.iceConnectionState !== \"completed\" &&\n\t\t\t\t\t\t\t\t\tscreen.webrtcStuff.pc.iceConnectionState !== \"connected\") {\n\t\t\t\t\t\t\t\t\t$(\"#streamscreen\").parent().parent().block({\n\t\t\t\t\t\t\t\t\t\tmessage: '<b>Publishing...</b>',\n\t\t\t\t\t\t\t\t\t\tcss: {\n\t\t\t\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\t\t\t\tcolor: 'white'\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonremotetrack: function (track, mid, on) {\n\t\t\t\t\t\t\t\t// the publisher stream is sendonly, we don't expect anything here\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\toncleanup: function () {\n\t\t\t\t\t\t\t\tJanus.log(\"got a cleanup notification\");\n\t\t\t\t\t\t\t\t$('#streamscreen').empty();\n\t\t\t\t\t\t\t\t$(\"#streamscreen\").parent().unblock();\n\t\t\t\t\t\t\t\tlocal_tracks = {};\n\t\t\t\t\t\t\t\tlocal_videos = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\terror: function (error) {\n\t\t\t\t\tJanus.error(error);\n\t\t\t\t},\n\t\t\t\tdestroyed: function () {\n\t\t\t\t\tJanus.log(\"Janus session id:\" + id + \" destroyed\");\n\t\t\t\t}\n\t\t\t});\n\n      // create new_remote_feed function \n      new_remote_feed = function (p_id, p_display) {\n\t      // a new feed has been published, create a new plugin handle and attach to it as a listener\n\t      source = p_id;\n\t      var _remote_feed = null;\n\t      janus.attach({\n\t      \t\tplugin: \"janus.plugin.videoroom\",\n\t      \t\topaqueId: opaque_id,\n\t      \t\tsuccess: function (p_plugin_handle) {\n\t      \t\t\t_remote_feed = p_plugin_handle;\n\t      \t\t\t_remote_feed.remote_tracks = {};\n\t      \t\t\t_remote_feed.remote_videos = 0;\n\t      \t\t\tJanus.log(\"plugin attached! (\" + _remote_feed.getPlugin() + \", id=\" + _remote_feed.getId() + \")\");\n\t      \t\t\tJanus.log(\"this is a subscriber\");\n\t      \t\t\t// we wait for the plugin to send us an offer\n\t      \t\t\tvar _listen = {\n\t      \t\t\t\trequest: \"join\",\n\t      \t\t\t\troom: room,\n\t      \t\t\t\tptype: \"subscriber\",\n\t      \t\t\t\tfeed: p_id\n\t      \t\t\t};\n\t      \t\t\t_remote_feed.send({ message: _listen });\n\t      \t\t},\n\t      \t\terror: function (p_error) {\n\t      \t\t\tJanus.error(\"error attaching plugin: \", p_error);\n\t      \t\t},\n\t      \t\ticeState: function (p_state) {\n\t      \t\t\tJanus.log(\"ICE state (feed #\" + _remote_feed.rfindex + \") changed to \" + p_state);\n\t      \t\t},\n\t      \t\twebrtcState: function (p_on) {\n\t      \t\t\tJanus.log(\"Janus says this WebRTC PeerConnection (feed #\" + _remote_feed.rfindex + \") is \" + (p_on ? \"up\" : \"down\") + \" now\");\n\t      \t\t},\n\t      \t\tslowLink: function (p_uplink, p_lost, p_mid) {\n\t      \t\t\tJanus.warn(\"Janus reports problems \" + (p_uplink ? \"sending\" : \"receiving\") +\n\t      \t\t\t\t\" packets on mid \" + p_mid + \" (\" + p_lost + \" lost packets)\");\n\t      \t\t},\n\t      \t\tonmessage: function (p_msg, p_jsep) {\n\t      \t\t\tJanus.debug(\"got a message (listener): \", p_msg);\n\t      \t\t\tvar _event = p_msg[\"videoroom\"];\n\t      \t\t\tJanus.debug(\"Janus event: \" + _event);\n\t      \t\t\tif (_event) {\n\t      \t\t\t\tif (_event === \"attached\") {\n\t      \t\t\t\t\t// subscriber created and attached\n\t      \t\t\t\t\tif (!spinner) {\n\t      \t\t\t\t\t\tvar _target = document.getElementById('#streamscreen');\n\t      \t\t\t\t\t\tspinner = new Spinner({ top: 100 }).spin(_target);\n\t      \t\t\t\t\t} else {\n\t      \t\t\t\t\t\tspinner.spin();\n\t      \t\t\t\t\t}\n\t      \t\t\t\t\tJanus.log(\"successfully attached to feed \" + id + \" (\" + p_display + \") in room \" + p_msg[\"room\"]);\n\t      \t\t\t\t}// else {\n\t      \t\t\t\t\t// what has just happened\n\t      \t\t\t\t\t//Janus.error(\"unexpected point of program. event: \" + _event);\n\t      \t\t\t\t//}\n\t      \t\t\t}\n\t      \t\t\tif (p_jsep) {\n\t      \t\t\t\tJanus.debug(\"handling SDP as well: \", p_jsep);\n\t      \t\t\t\t// Answer and attach\n\t      \t\t\t\t_remote_feed.createAnswer(\n\t      \t\t\t\t\t{\n\t      \t\t\t\t\t\tjsep: p_jsep,\n\t      \t\t\t\t\t\t// We only specify data channels here, as this way in\n\t      \t\t\t\t\t\t// case they were offered we'll enable them. Since we\n\t      \t\t\t\t\t\t// don't mention audio or video tracks, we autoaccept them\n\t      \t\t\t\t\t\t// as recvonly (since we won't capture anything ourselves)\n\t      \t\t\t\t\t\ttracks: [\n\t      \t\t\t\t\t\t\t{ type: 'data' }\n\t      \t\t\t\t\t\t],\n\t      \t\t\t\t\t\tsuccess: function (p_jsep) {\n\t      \t\t\t\t\t\t\tJanus.debug(\"got SDP!\", p_jsep);\n\t      \t\t\t\t\t\t\tvar _body = { request: \"start\", room: room };\n\t      \t\t\t\t\t\t\t_remote_feed.send({ message: _body, jsep: p_jsep });\n\t      \t\t\t\t\t\t},\n\t      \t\t\t\t\t\terror: function (p_error) {\n\t      \t\t\t\t\t\t\tJanus.error(\"WebRTC error:\", p_error);\n\t      \t\t\t\t\t\t}\n\t      \t\t\t\t\t});\n\t      \t\t\t}\n\t      \t\t},\n\t      \t\tonlocaltrack: function (p_track, p_on) {\n\t      \t\t\t// the subscriber stream is receive-only, we don't expect anything here\n\t      \t\t},\n\t      \t\tonremotetrack: function (p_track, p_mid, p_on) {\n\t      \t\t\tJanus.debug(\"remote track (mid=\" + p_mid + \") \" + (p_on ? \"added\" : \"removed\") + \":\", p_track);\n\t      \t\t\tif (!p_on) {\n\t      \t\t\t\t// Track removed, get rid of the stream and the rendering\n\t      \t\t\t\t$('#screenvideo' + p_mid).remove();\n\t      \t\t\t\tif (p_track.kind === \"video\") {\n\t      \t\t\t\t\tremote_videos--;\n\t      \t\t\t\t\tif (remote_videos === 0) {\n\t      \t\t\t\t\t\t// no video, at least for now: show a placeholder\n\t      \t\t\t\t\t\tif ($('#streamscreen .no-video-container').length === 0) {\n\t\t\t\t\t\t\t\t\tJanus.log(\"no remote video available\");\n\t      \t\t\t\t\t\t}\n\t      \t\t\t\t\t}\n\t      \t\t\t\t}\n\t      \t\t\t\tdelete remote_tracks[p_mid];\n\t      \t\t\t\treturn;\n\t      \t\t\t}\n\t      \t\t\t// If we're here, a new track was added\n\t      \t\t\tif (spinner !== undefined && spinner !== null) {\n\t      \t\t\t\tspinner.stop();\n\t      \t\t\t\tspinner = null;\n\t      \t\t\t}\n\t      \t\t\tif (p_track.kind === \"audio\") {\n\t      \t\t\t\t// new audio track: create a stream out of it, and use a hidden <audio> element\n\t      \t\t\t\t_stream = new MediaStream([p_track]);\n\t      \t\t\t\tremote_tracks[p_mid] = _stream;\n\t      \t\t\t\tJanus.log(\"created remote audio stream:\", _stream);\n\t      \t\t\t\t$('#streamscreen').append('<audio hidden id=\"screenvideo' + p_mid + '\" playsinline/>');\n\t      \t\t\t\t$('#screenvideo' + p_mid).get(0).volume = 0;\n\t      \t\t\t\tJanus.attachMediaStream($('#screenvideo' + p_mid).get(0), _stream);\n\t      \t\t\t\tvar _play_promise = $('#screenvideo' + p_mid).get(0).play();\n\t\t\t\t\t\tif (_play_promise !== undefined) {\n  \t\t\t\t\t\t  _play_promise.then(_ => {\n  \t\t\t\t\t\t    // play just started\n\t\t\t\t\t\t\t$('#screenvideo' + p_mid).get(0).volume = 1;\n  \t\t\t\t\t\t  })\n  \t\t\t\t\t\t  .catch(p_error => {\n  \t\t\t\t\t\t    //Janus.error(p_error);\n  \t\t\t\t\t\t  });\n  \t\t\t\t\t\t}\n\t      \t\t\t\tif (remote_videos === 0) {\n\t      \t\t\t\t\t// no video, at least for now: show a placeholder\n\t      \t\t\t\t\tif ($('#streamscreen .no-video-container').length === 0) {\n\t\t\t\t\t\t\t\tJanus.log(\"no remote video available\");\n\t      \t\t\t\t\t}\n\t      \t\t\t\t}\n\t      \t\t\t} else {\n\t      \t\t\t\t// new video track: create a stream out of it\n\t      \t\t\t\tremote_videos++;\n\t      \t\t\t\t$('#streamscreen .no-video-container').remove();\n\t      \t\t\t\t_stream = new MediaStream([p_track]);\n\t      \t\t\t\t_remote_feed.remote_tracks[p_mid] = _stream;\n\t      \t\t\t\tJanus.log(\"created remote video stream:\", _stream);\n\t      \t\t\t\t$('#streamscreen').append('<video muted id=\"screenvideo' + p_mid + '\" width=100% playsinline/>');\n\t      \t\t\t\t$('#screenvideo' + p_mid).get(0).volume = 0;\n\t      \t\t\t\tJanus.attachMediaStream($('#screenvideo' + p_mid).get(0), _stream);\n\t      \t\t\t\tvar _play_promise = $('#screenvideo' + p_mid).get(0).play();\n\t\t\t\t\t\tif (_play_promise !== undefined) {\n  \t\t\t\t\t\t  _play_promise.then(_ => {\n  \t\t\t\t\t\t    // play just started\n\t\t\t\t\t\t\t$('#screenvideo' + p_mid).get(0).volume = 1;\n  \t\t\t\t\t\t  })\n  \t\t\t\t\t\t  .catch(p_error => {\n  \t\t\t\t\t\t    //Janus.error(p_error);\n  \t\t\t\t\t\t  });\n  \t\t\t\t\t\t}\n\t      \t\t\t}\n\t      \t\t},\n\t      \t\toncleanup: function () {\n\t      \t\t\tJanus.log(\"got a cleanup notification (remote feed \" + p_id + \")\");\n\t      \t\t\t$('#waitingvideo').remove();\n\t      \t\t\tif (spinner) {\n\t      \t\t\t\tspinner.stop();\n\t      \t\t\t}\n\t      \t\t\tspinner = null;\n\t      \t\t\t_remote_feed.remote_tracks = {};\n\t      \t\t\t_remote_feed.remote_videos = 0;\n\t      \t\t}\n\t      \t});\n      };\n\n      return 0;\n  }, (p_debug_mode ? 1 : 0));\n}\n\nboost::leaf::result<int> w_janus_api_emc::share_screen(\n  _In_ const char* p_username,\n  _In_ const char* p_room_desc,\n  _In_ int p_bitrate,\n  _In_ std::function<void(double)> p_on_success) noexcept {\n\n  if(p_room_desc == nullptr || p_username == nullptr || p_bitrate <= 0){\n    return W_FAILURE(std::errc::invalid_argument, \"missing p_room_desc or p_username or p_bitrate is not valid\");\n  }\n\n  s_on_screen_shared_callback = std::move(p_on_success);\n\n  // clang-format off\n  return EM_ASM_INT({\n\t// check for screensharing extension    \n\tif (!Janus.isExtensionEnabled()) {\n\t\tJanus.error(\"this browser doesn't support screensharing (getDisplayMedia unavailable)\");\n\t    return;\n\t}\n\tcapture = \"screen\";\n\n\t// create a new room\n    var _desc = \"\" + UTF8ToString($1);\n    role = \"publisher\";\n    var create = {};\n    create.request= \"create\";\n    createdescription= _desc;\n    create.bitrate= $2;\n    createpublishers= 1;\n    screen.send({\n\t\tmessage: create, success: function (p_result) {\n\t\t\tif (p_result[\"error\"]) {\n     \t\t\tJanus.error(\"couldn't create room: \" + p_result[\"error\"]);\n     \t\t\treturn;\n     \t\t}\n     \t\tvar _event = p_result[\"videoroom\"];\n     \t\tJanus.debug(\"Event: \" + _event);\n     \t\tif (_event) {\n     \t\t\t// Our own screen sharing session has been created, join it\n     \t\t\troom = p_result[\"room\"];\n     \t\t\tJanus.log(\"screen sharing session created: \" + room);\n     \t\t\tvar _username = \"\" + UTF8ToString($0);\n     \t\t\tvar _register = {\n     \t\t\t\trequest: \"join\",\n     \t\t\t\troom: room,\n     \t\t\t\tptype: \"publisher\",\n     \t\t\t\tdisplay: _username\n\t\t      \t};\n\t\t    \tscreen.send({ message: _register });\n\t    \t}\n    \t}\n\t});\n    return 0;\n  }, p_username, p_room_desc, p_bitrate);\n}\n\nboost::leaf::result<int> w_janus_api_emc::join_room(\n\t_In_ double p_room_id,\n\t_In_ const char* p_username,\n    _In_ std::function<void(void)> p_on_success) noexcept\n{\n\tif(p_room_id <= 0 || p_username == nullptr){\n    \treturn W_FAILURE(std::errc::invalid_argument, \"p_room_id or p_username is not valid\");\n  \t}\n\n\ts_on_join_room_callback = std::move(p_on_success);\n\n  \treturn EM_ASM_INT({\n\t\t// join an existing screen sharing session\n\t\troom = $0;\n\t\trole = \"listener\";\n\t\tvar _username =  \"\" + UTF8ToString($1);\n\t\tvar _register = {};\n\t\t_register.request= \"join\";\n\t\t_register.room= room;\n\t\t_register.ptype= \"publisher\";\n\t\t_register.display= _username;\n\t\tscreen.send({ message: _register });\n    \treturn 0;\n  \t}, p_room_id, p_username);\n}\n\n                // clang-format on\n\n#endif // defined(WOLF_STREAM_JANUS) && defined(EMSCRIPTEN)\n"
  },
  {
    "path": "wolf/stream/janus/w_janus_api_emc.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_STREAM_JANUS) && defined(EMSCRIPTEN)\n\n#pragma once\n\n#include <list>\n#include <wolf/wolf.hpp>\n\nnamespace wolf::stream::janus {\nclass w_janus_api_emc {\npublic:\n  /**\n   * initialize the Janus library\n   * @param p_debug_mode, enable debug mode\n   * @param p_on_init_callback, on init callback\n   * @returns 0 on success\n   */\n  W_API static boost::leaf::result<int>\n  init(_In_ bool p_debug_mode,\n       _In_ std::function<void(int)> p_on_init_callback) noexcept;\n\n  /**\n   * create a Janus session and share current screen\n   * @param p_username, the username\n   * @param p_room_desc, a description for the room\n   * @param p_bitrate, the bitrate of stream\n   * @param p_on_success, a callback which will be raised on success\n   * @returns 0 on success\n   */\n  W_API static boost::leaf::result<int> share_screen(\n      _In_ const char *p_username, _In_ const char *p_room_desc,\n      _In_ int p_bitrate,\n      _In_ std::function<void(double /*p_room_id*/)> p_on_success) noexcept;\n\n  /**\n   * create a Janus session and share current screen\n   * @param p_room_id, an id of room\n   * @param p_username, the username\n   * @param p_on_success, a callback which will be raised on success\n   * @returns 0 on success\n   */\n  W_API static boost::leaf::result<int>\n  join_room(_In_ double p_room_id, _In_ const char *p_username,\n            _In_ std::function<void(void)> p_on_success) noexcept;\n};\n} // namespace wolf::stream::janus\n\n#endif // defined(WOLF_STREAM_JANUS) AND defined(EMSCRIPTEN)"
  },
  {
    "path": "wolf/stream/quic/datatypes/common_flags.hpp",
    "content": "#pragma once\n\n#include <msquic.h>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief The equivalent enum flags for QUIC_CONNECTION_SHUTDOWN_FLAGS.\n */\nenum class w_connection_shutdown_flag {\n    None = QUIC_CONNECTION_SHUTDOWN_FLAG_NONE,\n    Silent = QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT\n};\n\n/**\n * @brief The equivalent enum flags for QUIC_STREAM_OPEN_FLAGS.\n */\nenum class w_stream_open_flag {\n    None = QUIC_STREAM_OPEN_FLAG_NONE,\n    ZeroRTT = QUIC_STREAM_OPEN_FLAG_0_RTT,\n    Unidirectional = QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL\n};\n\n/**\n * @brief The equivalent enum flags for QUIC_STREAM_START_FLAGS.\n */\nenum class w_stream_start_flag {\n    None = QUIC_STREAM_START_FLAG_NONE,\n    Immediate = QUIC_STREAM_START_FLAG_IMMEDIATE,\n    FailBlocked = QUIC_STREAM_START_FLAG_FAIL_BLOCKED,\n    ShutdownOnFail = QUIC_STREAM_START_FLAG_SHUTDOWN_ON_FAIL,\n    IndicatePeerAccept = QUIC_STREAM_START_FLAG_INDICATE_PEER_ACCEPT,\n};\n\n/**\n * @brief The equivalent enum flags for QUIC_STREAM_SHUTDOWN_FLAGS.\n */\nenum class w_stream_shutdown_flag {\n    Graceful = QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL,\n    AbortSend = QUIC_STREAM_SHUTDOWN_FLAG_ABORT_SEND,\n    AbortReceive = QUIC_STREAM_SHUTDOWN_FLAG_ABORT_RECEIVE,\n    Immediate = QUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE,\n\n    Abort = QUIC_STREAM_SHUTDOWN_FLAG_ABORT,  // abort both (ABORT_SEND | ABORT_RECEIVE)\n};\n\n/**\n * @brief The equivalent enum flags for QUIC_RECEIVE_FLAGS.\n */\nenum class w_receive_flag {\n    None = QUIC_RECEIVE_FLAG_NONE,\n    ZeroRTT = QUIC_RECEIVE_FLAG_0_RTT,\n    Fin = QUIC_RECEIVE_FLAG_FIN\n};\n\n/**\n * @brief The equivalent enum flags for QUIC_SEND_FLAGS.\n */\nenum class w_send_flag {\n    None = QUIC_SEND_FLAG_NONE,\n    AllowZeroRTT = QUIC_SEND_FLAG_ALLOW_0_RTT,\n    Start = QUIC_SEND_FLAG_START,\n    Fin = QUIC_SEND_FLAG_FIN,\n    DataGramPriority = QUIC_SEND_FLAG_DGRAM_PRIORITY,\n    DelaySend = QUIC_SEND_FLAG_DELAY_SEND,\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_address.cpp",
    "content": "#include \"stream/quic/datatypes/w_address.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_address.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n\n#include <msquic.h>\n\n#include <cstdint>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief equivalent of QUIC_ADDRESS_FAMILY enum.\n */\nenum class w_address_family {\n    Unspecified = QUIC_ADDRESS_FAMILY_UNSPEC,\n    INET = QUIC_ADDRESS_FAMILY_INET,\n    INET6 = QUIC_ADDRESS_FAMILY_INET6\n};\n\n/**\n * @brief Wrapping QUIC_ADDRESS.\n *\n * Commonly used to open a listener.\n */\nclass W_API w_address {\n    friend class internal::w_raw_access;\n\npublic:\n    w_address(w_address_family p_address_family, std::uint16_t p_port) noexcept\n    {\n        set_address_family(p_address_family);\n        set_port(p_port);\n    }\n\n    /**\n     * @brief get address family.\n     */\n    [[nodiscard]] w_address_family get_address_family() const noexcept\n    {\n        return static_cast<w_address_family>(QuicAddrGetFamily(&_address));\n    }\n\n    /**\n     * @brief set address family.\n     */\n    void set_address_family(w_address_family p_address_family) noexcept\n    {\n        QuicAddrSetFamily(&_address, static_cast<QUIC_ADDRESS_FAMILY>(p_address_family));\n    }\n\n    /**\n     * @brief get port.\n     */\n    [[nodiscard]] std::uint16_t get_port() const noexcept\n    {\n        return QuicAddrGetPort(&_address);\n    }\n\n    /**\n     * @brief set port.\n     */\n    void set_port(std::uint16_t p_port) noexcept\n    {\n        QuicAddrSetPort(&_address, p_port);\n    }\n\nprivate:\n    auto raw() noexcept { return &_address; }\n    auto raw() const noexcept { return &_address; }\n\n    w_address(internal::w_raw_tag, const QUIC_ADDR& p_raw_addr)\n    {\n        std::memcpy(&_address, &p_raw_addr, sizeof(_address));\n    }\n\n    QUIC_ADDR _address{};\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_alpn.hpp",
    "content": "#pragma once\n\n#include <span>\n#include <string_view>\n\nnamespace wolf::stream::quic {\n\nusing w_alpn_view = std::span<std::uint8_t>;\n\ninline w_alpn_view as_alpn_view(w_alpn_view p_alpn_view)\n{\n    return p_alpn_view;\n}\n\ninline w_alpn_view as_alpn_view(const std::string_view p_str)\n{\n    return w_alpn_view((uint8_t*)p_str.data(), p_str.length());\n}\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_credential_config.cpp",
    "content": "#include \"stream/quic/datatypes/w_credential_config.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_credential_config.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n#include \"system/w_flags.hpp\"\n#include \"system/w_overloaded.hpp\"\n\n#include <msquic.h>\n\n#include <array>\n#include <memory>\n#include <span>\n#include <string>\n#include <variant>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief Equivalent flags enum to QUIC_CREDENTIAL_FLAG enum.\n */\nenum class w_credential_flag {\n    None                               = QUIC_CREDENTIAL_FLAG_NONE,\n    Client                             = QUIC_CREDENTIAL_FLAG_CLIENT,\n    LoadAsynchronous                   = QUIC_CREDENTIAL_FLAG_LOAD_ASYNCHRONOUS,\n    NoCertificationValidation          = QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION,\n    EnableOCSP                         = QUIC_CREDENTIAL_FLAG_ENABLE_OCSP,\n    IndicateCertificateReceived        = QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED,\n    DeferCertificateValidation         = QUIC_CREDENTIAL_FLAG_DEFER_CERTIFICATE_VALIDATION,\n    RequireClientAuthenticate          = QUIC_CREDENTIAL_FLAG_REQUIRE_CLIENT_AUTHENTICATION,\n    UseTlsBuiltinCertificateValidation = QUIC_CREDENTIAL_FLAG_USE_TLS_BUILTIN_CERTIFICATE_VALIDATION,\n    RevocationCheckEndCert             = QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_END_CERT,\n    RevocationCheckChain               = QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CHAIN,\n    RevocationCheckChainExcludeRoot    = QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,\n    IgnoreNoRevocationCheck            = QUIC_CREDENTIAL_FLAG_IGNORE_NO_REVOCATION_CHECK,\n    IgnoreRevocationOffline            = QUIC_CREDENTIAL_FLAG_IGNORE_REVOCATION_OFFLINE,\n    SetAllowedCipherSuites             = QUIC_CREDENTIAL_FLAG_SET_ALLOWED_CIPHER_SUITES,\n    UsePortableCertificates            = QUIC_CREDENTIAL_FLAG_USE_PORTABLE_CERTIFICATES,\n    UseSuppliedCredentials             = QUIC_CREDENTIAL_FLAG_USE_SUPPLIED_CREDENTIALS,\n    UseSystemMapper                    = QUIC_CREDENTIAL_FLAG_USE_SYSTEM_MAPPER,\n    CacheOnlyURLRetrieval              = QUIC_CREDENTIAL_FLAG_CACHE_ONLY_URL_RETRIEVAL,\n    RevocationCheckCacheOnly           = QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CACHE_ONLY,\n    InprocPeerCertificate              = QUIC_CREDENTIAL_FLAG_INPROC_PEER_CERTIFICATE,\n    SetCACertificateFile               = QUIC_CREDENTIAL_FLAG_SET_CA_CERTIFICATE_FILE\n};\n\n/**\n * @brief An empty tag type indicating no certificate.\n */\nclass W_API w_certificate_none { /* nothing. tag type. */ };\n\n/**\n * @brief Wrapper of QUIC_CERTIFICATE_HASH.\n *\n * Holds sha1 hash binary digest (20 bytes).\n */\nclass W_API w_certificate_hash {\n    friend class internal::w_raw_access;\n\npublic:\n    constexpr static auto hash_size = 20;\n\n    /**\n     * @brief construct certificate with given sha1 bytes/digest.\n     * @param p_hash sha1 bytes/digest.\n     */\n    explicit w_certificate_hash(std::span<const uint8_t, hash_size> p_hash)\n    {\n        std::memcpy(_cert.ShaHash, p_hash.data(), hash_size);\n    }\n\n    w_certificate_hash(const w_certificate_hash& p_other) noexcept\n        : w_certificate_hash(p_other._cert.ShaHash)\n    {}\n\n    w_certificate_hash& operator=(const w_certificate_hash& p_other) noexcept\n    {\n        std::memcpy(_cert.ShaHash, p_other._cert.ShaHash, hash_size);\n        return *this;\n    }\n\n    ~w_certificate_hash() { /* nothing */ }\n\nprivate:\n    auto raw() noexcept { return &_cert; }\n    auto raw() const noexcept { return &_cert; }\n\n    QUIC_CERTIFICATE_HASH _cert;\n};\n\n/**\n * @brief Wrapper of QUIC_CERTIFICATE_FILE.\n *\n * Holding file paths of certificate and key,\n * which are loaded when loading credentials into\n * configuration handle.\n */\nclass w_certificate_file {\n    friend class internal::w_raw_access;\n\npublic:\n    w_certificate_file(std::string p_cert_file_path, std::string p_key_file_path)\n        : _cert_file_path(std::move(p_cert_file_path))\n        , _key_file_path(std::move(p_key_file_path))\n    {\n        _cert.CertificateFile = _cert_file_path.c_str();\n        _cert.PrivateKeyFile = _key_file_path.c_str();\n    }\n\n    w_certificate_file(const w_certificate_file& p_other)\n        : w_certificate_file(p_other._cert_file_path, p_other._key_file_path)\n    {}\n\n    w_certificate_file(w_certificate_file&& p_other)\n        : w_certificate_file(std::move(p_other._cert_file_path), std::move(p_other._key_file_path))\n    {}\n\n    w_certificate_file& operator=(const w_certificate_file& p_other)\n    {\n        _cert_file_path = p_other._cert_file_path;\n        _key_file_path = p_other._key_file_path;\n        _cert.CertificateFile = _cert_file_path.c_str();\n        _cert.PrivateKeyFile = _key_file_path.c_str();\n        return *this;\n    }\n\n    w_certificate_file& operator=(w_certificate_file&& p_other)\n    {\n        _cert_file_path = std::move(p_other._cert_file_path);\n        _key_file_path = std::move(p_other._key_file_path);\n        _cert.CertificateFile = _cert_file_path.c_str();\n        _cert.PrivateKeyFile = _key_file_path.c_str();\n        return *this;\n    }\n\n    ~w_certificate_file() { /* nothing */ }\n\nprivate:\n    auto raw() noexcept { return &_cert; }\n    auto raw() const noexcept { return &_cert; }\n\n    std::string _cert_file_path;\n    std::string _key_file_path;\n\n    QUIC_CERTIFICATE_FILE _cert;\n};\n\n/**\n * @brief Wrapper of QUIC_CREDENTIAL_CONFIG.\n *\n * Used to setup configuration handle.\n */\nclass w_credential_config {\n    friend class internal::w_raw_access;\n\npublic:\n    using cert_variant_type = std::variant<w_certificate_none,\n                                           w_certificate_hash,\n                                           w_certificate_file>;\n\n    /**\n     * @brief construct credential config with given certificate type, and flags.\n     * @param p_cert    a supported certificate object. (w_certificate_<none/hash/file>)\n     * @param p_flags   flags to associate with the credentials.\n     */\n    explicit w_credential_config(\n                    cert_variant_type p_cert,\n                    wolf::w_flags<w_credential_flag> p_flags = w_credential_flag::None) noexcept\n        : _cert_variant(p_cert)\n    {\n        std::memset(&_config, 0, sizeof(_config));\n\n        _config.Flags = static_cast<QUIC_CREDENTIAL_FLAGS>(p_flags.to_underlying());\n\n        setup_raw_config_from_variant(_cert_variant);\n    }\n\n    w_credential_config(const w_credential_config& p_other)\n        : w_credential_config(p_other._cert_variant,\n                              static_cast<w_credential_flag>(p_other._config.Flags))\n    {}\n\n    w_credential_config(w_credential_config&& p_other)\n        : w_credential_config(std::move(p_other._cert_variant),\n                              static_cast<w_credential_flag>(p_other._config.Flags))\n    {}\n\n    w_credential_config& operator=(const w_credential_config& p_other)\n    {\n        _cert_variant = p_other._cert_variant;\n        setup_raw_config_from_variant(_cert_variant);\n        return *this;\n    }\n\n    w_credential_config& operator=(w_credential_config&& p_other)\n    {\n        _cert_variant = std::move(p_other._cert_variant);\n        setup_raw_config_from_variant(_cert_variant);\n        return *this;\n    }\n\n    ~w_credential_config() { /* nothing */ }\n\nprivate:\n    void setup_raw_config_from_variant(cert_variant_type& p_cert_variant)\n    {\n        std::visit(w_overloaded{\n            [this](w_certificate_none&) {\n                _config.Type = QUIC_CREDENTIAL_TYPE_NONE;\n            },\n            [this](w_certificate_hash& p_cert) {\n                _config.Type = QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH;\n                _config.CertificateHash = internal::w_raw_access::raw(p_cert);\n            },\n            [this](w_certificate_file& p_cert) {\n                _config.Type = QUIC_CREDENTIAL_TYPE_CERTIFICATE_FILE;\n                _config.CertificateFile = internal::w_raw_access::raw(p_cert);\n            }\n        }, p_cert_variant);\n    }\n\n    auto raw() noexcept { return &_config; }\n    auto raw() const noexcept { return &_config; }\n\n    cert_variant_type _cert_variant;\n    QUIC_CREDENTIAL_CONFIG _config;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_new_connection_info.cpp",
    "content": "#include \"stream/quic/datatypes/w_new_connection_info.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_new_connection_info.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/datatypes/w_address.hpp\"\n\n#include <msquic.h>\n\n#include <cstdint>\n#include <string_view>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief Accessor wrapper of QUIC_NEW_CONNECTION_INFO type.\n *\n * This class wraps the raw C type, and provides simple accessor methods.\n */\nclass W_API w_new_connection_info {\n    friend class internal::w_raw_access;\n\npublic:\n    w_new_connection_info() = delete;\n\n    /**\n     * @brief negotiated quic version.\n     */\n    [[nodiscard]] auto quic_version() const\n    {\n        return _conn_info.QuicVersion;\n    }\n\n    /**\n     * @brief the local address of the new incoming connection.\n     */\n    [[nodiscard]] w_address local_address() const\n    {\n        return internal::w_raw_access::from_raw<w_address>(*_conn_info.LocalAddress);\n    }\n\n    /**\n     * @brief the remote address of the new incoming connection.\n     */\n    [[nodiscard]] w_address remote_address() const\n    {\n        return internal::w_raw_access::from_raw<w_address>(*_conn_info.RemoteAddress);\n    }\n\n    /**\n     * @brief the server name (SNI) of the new incoming connection.\n     */\n    [[nodiscard]] std::string_view server_name() const\n    {\n        return std::string_view(_conn_info.ServerName, _conn_info.ServerNameLength);\n    }\n\n    /**\n     * @brief the negotiated ALPN between server and client.\n     */\n    [[nodiscard]] std::string_view negotiated_alpn() const\n    {\n        auto c_str = (const char*)(_conn_info.NegotiatedAlpn);\n        return std::string_view(c_str, _conn_info.NegotiatedAlpnLength);\n    }\n\nprivate:\n    w_new_connection_info(internal::w_raw_tag, const QUIC_NEW_CONNECTION_INFO& p_conn_info)\n        : _conn_info(p_conn_info)\n    {}\n\n    QUIC_NEW_CONNECTION_INFO _conn_info = { 0 };\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_registration_config.cpp",
    "content": "#include \"stream/quic/datatypes/w_registration_config.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_registration_config.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n\n#include <msquic.h>\n\n#include <string>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief equivalent enum to QUIC_EXECUTION_PROFILE enum.\n *\n * Used with registration config to specify aimed execution profile.\n */\nenum class w_execution_profile {\n    LowLatency = QUIC_EXECUTION_PROFILE_LOW_LATENCY,\n    MaxThroughput = QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT,\n    Scavenger = QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER,\n    RealTime = QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME\n};\n\n/**\n * @brief wrapper around QUIC_REGISTRATION_CONFIG.\n */\nclass w_registration_config {\n    friend class internal::w_raw_access;\n\npublic:\n    /**\n     * @brief construct simple registration config.\n     */\n    w_registration_config(std::string p_app_name,\n                          w_execution_profile p_profile = w_execution_profile::LowLatency) noexcept\n        : _app_name(std::move(p_app_name))\n    {\n        _config.AppName = _app_name.c_str();\n        _config.ExecutionProfile = static_cast<QUIC_EXECUTION_PROFILE>(p_profile);\n    }\n\n    /**\n     * @brief get app name.\n     */\n    [[nodiscard]] const std::string& get_app_name() const noexcept\n    {\n        return _app_name;\n    }\n\n    /**\n     * @brief get execution profile.\n     */\n    [[nodiscard]] w_execution_profile get_execution_profile() const noexcept\n    {\n        return static_cast<w_execution_profile>(_config.ExecutionProfile);\n    }\n\n    /**\n     * @brief set execution profile.\n     */\n    void set_execution_profile(w_execution_profile p_profile) noexcept\n    {\n        _config.ExecutionProfile = static_cast<QUIC_EXECUTION_PROFILE>(p_profile);\n    }\n\nprivate:\n    auto raw() noexcept { return &_config; }\n    auto raw() const noexcept { return &_config; }\n\n    const std::string _app_name;\n    QUIC_REGISTRATION_CONFIG _config = { 0 };\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_settings.cpp",
    "content": "#include \"stream/quic/datatypes/w_settings.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_settings.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n\n#include <msquic.h>\n\n#include <optional>\n#include <memory>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief Equivalent enum of QUIC_SERVER_RESUMPTION_LEVEL.\n *\n * Its values are defined in QUIC_SETTINGS document in msquic.\n */\nenum class w_server_resumption_level {\n    NoResume = QUIC_SERVER_NO_RESUME,\n    ResumeOnly = QUIC_SERVER_RESUME_ONLY,\n    ResumeAndZeroRTT = QUIC_SERVER_RESUME_AND_ZERORTT\n};\n\n/**\n * @brief Equivalent enum of QUIC_CONGESTION_CONTROL_ALGORITHM.\n */\nenum class w_congestion_control_algorithm {\n    Cubic = QUIC_CONGESTION_CONTROL_ALGORITHM_CUBIC,\n    Max = QUIC_CONGESTION_CONTROL_ALGORITHM_MAX\n};\n\n/**\n * @brief Wrapper of QUIC_SETTINGS.\n *\n * QUIC_SETTINGS has a set of fields to tweak\n * application's protocol behavior.\n *\n * A use-case of it to setup the configuration handle\n * for registration execution context.\n *\n * For each field in QUIC_SETTINGS, an equivalent\n * std::optional wrapped typed field has been defined.\n *\n * This type has and should be kept with support of aggregate initialization.\n */\nclass w_settings {\n    friend class internal::w_raw_access;\n\npublic:\n    std::optional<std::uint64_t>                  max_bytes_per_key;\n    std::optional<std::uint64_t>                  handshake_idle_timeout_ms;\n    std::optional<std::uint64_t>                  idle_timeout_ms;\n    std::optional<std::uint64_t>                  mtu_discovery_search_complete_timeout_us;\n    std::optional<std::uint32_t>                  tls_client_max_send_buffer;\n    std::optional<std::uint32_t>                  tls_server_max_send_buffer;\n    std::optional<std::uint32_t>                  stream_recv_window_default;\n    std::optional<std::uint32_t>                  stream_recv_buffer_default;\n    std::optional<std::uint32_t>                  conn_flow_control_window;\n    std::optional<std::uint32_t>                  max_worker_queue_delay_us;\n    std::optional<std::uint32_t>                  max_stateless_operations;\n    std::optional<std::uint32_t>                  initial_window_packets;\n    std::optional<std::uint32_t>                  send_idle_timeout_ms;\n    std::optional<std::uint32_t>                  initial_rtt_ms;\n    std::optional<std::uint32_t>                  max_ack_delay_ms;\n    std::optional<std::uint32_t>                  disconnect_timeout_ms;\n    std::optional<std::uint32_t>                  keep_alive_interval_ms;\n    std::optional<w_congestion_control_algorithm> congestion_control_algorithm;\n    std::optional<std::uint16_t>                  peer_bidi_stream_count;\n    std::optional<std::uint16_t>                  peer_unidi_stream_count;\n    std::optional<std::uint16_t>                  max_binding_stateless_operations;\n    std::optional<std::uint16_t>                  stateless_operation_expiration_ms;\n    std::optional<std::uint16_t>                  minimum_mtu;\n    std::optional<std::uint16_t>                  maximum_mtu;\n    std::optional<bool>                           send_buffering_enabled;\n    std::optional<bool>                           pacing_enabled;\n    std::optional<bool>                           migration_enabled;\n    std::optional<bool>                           datagram_receive_enabled;\n    std::optional<w_server_resumption_level>      server_resumption_level;\n    std::optional<bool>                           grease_quic_bit_enabled;\n    std::optional<bool>                           ecn_enabled;\n    std::optional<std::uint8_t>                   max_operations_per_drain;\n    std::optional<std::uint8_t>                   mtu_discovery_missing_probe_count;\n    std::optional<std::uint32_t>                  dest_cid_update_idle_timeout_ms;\n\nprivate:\n    auto raw() const noexcept\n    {\n        QUIC_SETTINGS ret;\n        std::memset(&ret, 0, sizeof(ret));\n\n        // NOTE the default value used by `value_or` is irrelevant to settings\n        //      as if there isn't a value, then the `IsSet` correspondant flag will be false too.\n\n        ret.MaxBytesPerKey = max_bytes_per_key.value_or(0);\n        ret.IsSet.MaxBytesPerKey = max_bytes_per_key.has_value();\n\n        ret.HandshakeIdleTimeoutMs = handshake_idle_timeout_ms.value_or(0);\n        ret.IsSet.HandshakeIdleTimeoutMs = handshake_idle_timeout_ms.has_value();\n\n        ret.IdleTimeoutMs = idle_timeout_ms.value_or(0);\n        ret.IsSet.IdleTimeoutMs = idle_timeout_ms.has_value();\n\n        ret.MtuDiscoverySearchCompleteTimeoutUs =\n                mtu_discovery_search_complete_timeout_us.value_or(0);\n        ret.IsSet.MtuDiscoverySearchCompleteTimeoutUs =\n                mtu_discovery_search_complete_timeout_us.has_value();\n\n        ret.TlsClientMaxSendBuffer = tls_client_max_send_buffer.value_or(0);\n        ret.IsSet.TlsClientMaxSendBuffer = tls_client_max_send_buffer.has_value();\n\n        ret.TlsServerMaxSendBuffer = tls_server_max_send_buffer.value_or(0);\n        ret.IsSet.TlsServerMaxSendBuffer = tls_server_max_send_buffer.has_value();\n\n        ret.StreamRecvWindowDefault = stream_recv_window_default.value_or(0);\n        ret.IsSet.StreamRecvWindowDefault = stream_recv_window_default.has_value();\n\n        ret.StreamRecvBufferDefault = stream_recv_buffer_default.value_or(0);\n        ret.IsSet.StreamRecvBufferDefault = stream_recv_buffer_default.has_value();\n\n        ret.ConnFlowControlWindow = conn_flow_control_window.value_or(0);\n        ret.IsSet.ConnFlowControlWindow = conn_flow_control_window.has_value();\n\n        ret.MaxWorkerQueueDelayUs = max_worker_queue_delay_us.value_or(0);\n        ret.IsSet.MaxWorkerQueueDelayUs = max_worker_queue_delay_us.has_value();\n\n        ret.MaxStatelessOperations = max_stateless_operations.value_or(0);\n        ret.IsSet.MaxStatelessOperations = max_stateless_operations.has_value();\n\n        ret.InitialWindowPackets = initial_window_packets.value_or(0);\n        ret.IsSet.InitialWindowPackets = initial_window_packets.has_value();\n\n        ret.SendIdleTimeoutMs = send_idle_timeout_ms.value_or(0);\n        ret.IsSet.SendIdleTimeoutMs = send_idle_timeout_ms.has_value();\n\n        ret.InitialRttMs = initial_rtt_ms.value_or(0);\n        ret.IsSet.InitialRttMs = initial_rtt_ms.has_value();\n\n        ret.MaxAckDelayMs = max_ack_delay_ms.value_or(0);\n        ret.IsSet.MaxAckDelayMs = max_ack_delay_ms.has_value();\n\n        ret.DisconnectTimeoutMs = disconnect_timeout_ms.value_or(0);\n        ret.IsSet.DisconnectTimeoutMs = disconnect_timeout_ms.has_value();\n\n        ret.KeepAliveIntervalMs = keep_alive_interval_ms.value_or(0);\n        ret.IsSet.KeepAliveIntervalMs = keep_alive_interval_ms.has_value();\n\n        ret.CongestionControlAlgorithm = static_cast<QUIC_CONGESTION_CONTROL_ALGORITHM>(\n            congestion_control_algorithm.value_or(w_congestion_control_algorithm::Cubic)\n        );\n        ret.IsSet.CongestionControlAlgorithm = congestion_control_algorithm.has_value();\n\n        ret.PeerBidiStreamCount = peer_bidi_stream_count.value_or(0);\n        ret.IsSet.PeerBidiStreamCount = peer_bidi_stream_count.has_value();\n\n        ret.PeerUnidiStreamCount = peer_unidi_stream_count.value_or(0);\n        ret.IsSet.PeerUnidiStreamCount = peer_unidi_stream_count.has_value();\n\n        ret.MaxBindingStatelessOperations = max_binding_stateless_operations.value_or(0);\n        ret.IsSet.MaxBindingStatelessOperations = max_binding_stateless_operations.has_value();\n\n        ret.StatelessOperationExpirationMs = stateless_operation_expiration_ms.value_or(0);\n        ret.IsSet.StatelessOperationExpirationMs = stateless_operation_expiration_ms.has_value();\n\n        ret.MinimumMtu = minimum_mtu.value_or(0);\n        ret.IsSet.MinimumMtu = minimum_mtu.has_value();\n\n        ret.MaximumMtu = maximum_mtu.value_or(0);\n        ret.IsSet.MaximumMtu = maximum_mtu.has_value();\n\n        ret.SendBufferingEnabled = send_buffering_enabled.value_or(0);\n        ret.IsSet.SendBufferingEnabled = send_buffering_enabled.has_value();\n\n        ret.PacingEnabled = pacing_enabled.value_or(0);\n        ret.IsSet.PacingEnabled = pacing_enabled.has_value();\n\n        ret.MigrationEnabled = migration_enabled.value_or(0);\n        ret.IsSet.MigrationEnabled = migration_enabled.has_value();\n\n        ret.DatagramReceiveEnabled = datagram_receive_enabled.value_or(0);\n        ret.IsSet.DatagramReceiveEnabled = datagram_receive_enabled.has_value();\n\n        ret.ServerResumptionLevel = static_cast<QUIC_SERVER_RESUMPTION_LEVEL>(\n            server_resumption_level.value_or(w_server_resumption_level::NoResume)\n        );\n        ret.IsSet.ServerResumptionLevel = server_resumption_level.has_value();\n\n        ret.GreaseQuicBitEnabled = grease_quic_bit_enabled.value_or(0);\n        ret.IsSet.GreaseQuicBitEnabled = grease_quic_bit_enabled.has_value();\n\n        ret.EcnEnabled = ecn_enabled.value_or(0);\n        ret.IsSet.EcnEnabled = ecn_enabled.has_value();\n\n        ret.MaxOperationsPerDrain = max_operations_per_drain.value_or(0);\n        ret.IsSet.MaxOperationsPerDrain = max_operations_per_drain.has_value();\n\n        ret.MtuDiscoveryMissingProbeCount = mtu_discovery_missing_probe_count.value_or(0);\n        ret.IsSet.MtuDiscoveryMissingProbeCount = mtu_discovery_missing_probe_count.has_value();\n\n        ret.DestCidUpdateIdleTimeoutMs = dest_cid_update_idle_timeout_ms.value_or(0);\n        ret.IsSet.DestCidUpdateIdleTimeoutMs = dest_cid_update_idle_timeout_ms.has_value();\n\n        return ret;\n    }\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_status.cpp",
    "content": "#include \"stream/quic/datatypes/w_status.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/datatypes/w_status.hpp",
    "content": "#pragma once\n\n#include <msquic.h>\n\n#include \"wolf.hpp\"\n\n#include <string_view>\n\nnamespace wolf::stream::quic {\n\nnamespace internal {\n\ninline const char* status_to_str(QUIC_STATUS p_status)\n{\n    switch (p_status) {\n    case QUIC_STATUS_SUCCESS:                 return \"success\";\n    case QUIC_STATUS_PENDING:                 return \"pending\";\n    case QUIC_STATUS_CONTINUE:                return \"continue\";\n    case QUIC_STATUS_ABORTED:                 return \"aborted\";\n    case QUIC_STATUS_UNREACHABLE:             return \"unreachable\";\n    case QUIC_STATUS_OUT_OF_MEMORY:           return \"out-of-memory\";\n    case QUIC_STATUS_NOT_SUPPORTED:           return \"not-supported\";\n    case QUIC_STATUS_NOT_FOUND:               return \"not-found\";\n    case QUIC_STATUS_BUFFER_TOO_SMALL:        return \"buffer-too-small\";\n    case QUIC_STATUS_USER_CANCELED:           return \"user-canceled\";\n    case QUIC_STATUS_INVALID_PARAMETER:       return \"invalid-parameter\";\n    case QUIC_STATUS_INVALID_STATE:           return \"invalid-state\";\n    case QUIC_STATUS_INTERNAL_ERROR:          return \"internal-error\";\n    case QUIC_STATUS_HANDSHAKE_FAILURE:       return \"handshake-failure\";\n    case QUIC_STATUS_INVALID_ADDRESS:         return \"invalid-address\";\n    case QUIC_STATUS_ADDRESS_IN_USE:          return \"address-in-use\";\n    case QUIC_STATUS_CONNECTION_TIMEOUT:      return \"connection-timeout\";\n    case QUIC_STATUS_CONNECTION_IDLE:         return \"connection-idle\";\n    case QUIC_STATUS_CONNECTION_REFUSED:      return \"connection-refused\";\n    case QUIC_STATUS_PROTOCOL_ERROR:          return \"protocol-error\";\n    case QUIC_STATUS_VER_NEG_ERROR:           return \"version-negotiation-error\";\n    case QUIC_STATUS_ALPN_NEG_FAILURE:        return \"alpn-negotiation-error\";\n    case QUIC_STATUS_STREAM_LIMIT_REACHED:    return \"stream-limit-reached\";\n    case QUIC_STATUS_TLS_ERROR:               return \"tls-error\";\n    case QUIC_STATUS_BAD_CERTIFICATE:         return \"bad-certificate\";\n    case QUIC_STATUS_REQUIRED_CERTIFICATE:    return \"required-certificate\";\n    case QUIC_STATUS_REVOKED_CERTIFICATE:     return \"revoked-certificate\";\n    case QUIC_STATUS_UNKNOWN_CERTIFICATE:     return \"unkown-certificate\";\n    case QUIC_STATUS_EXPIRED_CERTIFICATE:     return \"expired-certificate\";\n    case QUIC_STATUS_ALPN_IN_USE:             return \"alpn-in-use\";\n    case QUIC_STATUS_CERT_EXPIRED:            return \"cert-expired\";\n    case QUIC_STATUS_CERT_NO_CERT:            return \"no-cert\";\n    case QUIC_STATUS_CERT_UNTRUSTED_ROOT:     return \"cert-untrusted-root\";\n    default:\n        return \"unknown\";\n    }\n}\n\n}  // namespace internal\n\n/**\n * @brief equivalent of QUIC_STATUS.\n */\nenum class w_status_code {\n    Success                   = QUIC_STATUS_SUCCESS,\n    Pending                   = QUIC_STATUS_PENDING,\n    Continue                  = QUIC_STATUS_CONTINUE,\n    Aborted                   = QUIC_STATUS_ABORTED,\n    Unreachable               = QUIC_STATUS_UNREACHABLE,\n    OutOfMemory               = QUIC_STATUS_OUT_OF_MEMORY,\n    NotSupported              = QUIC_STATUS_NOT_SUPPORTED,\n    NotFound                  = QUIC_STATUS_NOT_FOUND,\n    BufferTooSmall            = QUIC_STATUS_BUFFER_TOO_SMALL,\n    UserCancelled             = QUIC_STATUS_USER_CANCELED,\n    InvalidParameter          = QUIC_STATUS_INVALID_PARAMETER,\n    InvalidState              = QUIC_STATUS_INVALID_STATE,\n    InternalError             = QUIC_STATUS_INTERNAL_ERROR,\n    HandshakeFailure          = QUIC_STATUS_HANDSHAKE_FAILURE,\n    InvalidAddress            = QUIC_STATUS_INVALID_ADDRESS,\n    AddressInUse              = QUIC_STATUS_ADDRESS_IN_USE,\n    ConnectionTimeout         = QUIC_STATUS_CONNECTION_TIMEOUT,\n    ConnectionIdle            = QUIC_STATUS_CONNECTION_IDLE,\n    ConnectionRefused         = QUIC_STATUS_CONNECTION_REFUSED,\n    ProtocolError             = QUIC_STATUS_PROTOCOL_ERROR,\n    VersionNegotiationError   = QUIC_STATUS_VER_NEG_ERROR,\n    AlpnNegotiationFailure    = QUIC_STATUS_ALPN_NEG_FAILURE,\n    StreamLimitReached        = QUIC_STATUS_STREAM_LIMIT_REACHED,\n    TlsError                  = QUIC_STATUS_TLS_ERROR,\n    BadCertificate            = QUIC_STATUS_BAD_CERTIFICATE,\n    RequiredCertificate       = QUIC_STATUS_REQUIRED_CERTIFICATE,\n    RevokedCertificate        = QUIC_STATUS_REVOKED_CERTIFICATE,\n    UnknonwCertificate        = QUIC_STATUS_UNKNOWN_CERTIFICATE,\n    ExpiredCertificate        = QUIC_STATUS_EXPIRED_CERTIFICATE,\n    AlpnInUse                 = QUIC_STATUS_ALPN_IN_USE,\n    CertExpired               = QUIC_STATUS_CERT_EXPIRED,\n    CertNoCert                = QUIC_STATUS_CERT_NO_CERT,\n    CertUntrustedRoot         = QUIC_STATUS_CERT_UNTRUSTED_ROOT\n};\n\n/**\n * @brief A helper utility providing characteristics of QUIC_STATUS.\n *\n * Providing helpers such as its QUIC_SUCCEEDED/QUIC_FAILED through\n * succeeded/failed methods, along with implicit bool conversion\n * equivalent to QUIC_SUCCEEDED macro.\n */\nclass W_API w_status {\npublic:\n    constexpr w_status(QUIC_STATUS p_code) noexcept\n        : _status_code(static_cast<w_status_code>(p_code))\n    {}\n\n    constexpr w_status(w_status_code p_code) noexcept\n        : _status_code(p_code)\n    {}\n\n    /**\n     * @brief whether status indicates succession or not.\n     */\n    [[nodiscard]] constexpr bool succeeded() const noexcept\n    {\n        return QUIC_SUCCEEDED(static_cast<QUIC_STATUS>(_status_code));\n    }\n\n    /**\n     * @brief whether status indicates failure or not.\n     */\n    [[nodiscard]] constexpr bool failed() const noexcept\n    {\n        return QUIC_FAILED(static_cast<QUIC_STATUS>(_status_code));\n    }\n\n    constexpr operator bool() const noexcept\n    {\n        return succeeded();\n    }\n\n    constexpr operator w_status_code() const noexcept\n    {\n        return _status_code;\n    }\n\nprivate:\n    w_status_code _status_code = w_status_code::Success;\n};\n\n/**\n * @brief convert given status code to an equivalent short string.\n */\ninline std::string_view status_to_str(w_status_code p_status_code)\n{\n    return internal::status_to_str(static_cast<QUIC_STATUS>(p_status_code));\n}\n\n/**\n * @brief convert given status to an equivalent short string.\n */\ninline std::string_view status_to_str(w_status p_status)\n{\n    return internal::status_to_str(static_cast<QUIC_STATUS>(w_status_code(p_status)));\n}\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/events/w_connection_event.cpp",
    "content": "#include \"stream/quic/events/w_connection_event.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/events/w_connection_event.hpp",
    "content": "#pragma once\n\n#include \"system/w_flags.hpp\"\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/internal/w_msquic_api.hpp\"\n#include \"stream/quic/datatypes/common_flags.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n#include \"stream/quic/handles/w_stream.hpp\"\n\n#include <msquic.h>\n\n// NOTE windows.h must be included after msquic.h\n//      due to some declaration issues.\n#include \"wolf.hpp\"\n\n#include <string_view>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief Wrapper around CONNECTED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_connected {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_connected() = delete;\n    w_connection_event_connected(const w_connection_event_connected&) = delete;\n    w_connection_event_connected(w_connection_event_connected&&) = delete;\n\n    [[nodiscard]] bool session_resumed() const noexcept\n    {\n        return _event->CONNECTED.SessionResumed;\n    }\n\n    [[nodiscard]] std::string_view negotiated_alpn() const noexcept\n    {\n        return std::string_view(\n            (const char*)_event->CONNECTED.NegotiatedAlpn,\n            _event->CONNECTED.NegotiatedAlpnLength\n        );\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_connected(internal::w_raw_tag, QUIC_CONNECTION_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around SHUTDOWN_INITIATED_BY_PEER variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_shutdown_initiated_by_peer {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_shutdown_initiated_by_peer() = delete;\n    w_connection_event_shutdown_initiated_by_peer(const w_connection_event_shutdown_initiated_by_peer&) = delete;\n    w_connection_event_shutdown_initiated_by_peer(w_connection_event_shutdown_initiated_by_peer&&) = delete;\n\n    [[nodiscard]] auto error_code() const noexcept\n    {\n        return _event->SHUTDOWN_INITIATED_BY_PEER.ErrorCode;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_shutdown_initiated_by_peer(internal::w_raw_tag, QUIC_CONNECTION_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around LOCAL_ADDRESS_CHANGED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_local_address_changed {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_local_address_changed() = delete;\n    w_connection_event_local_address_changed(const w_connection_event_local_address_changed&) = delete;\n    w_connection_event_local_address_changed(w_connection_event_local_address_changed&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_local_address_changed(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around PEER_ADDRESS_CHANGED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_peer_address_changed {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_peer_address_changed() = delete;\n    w_connection_event_peer_address_changed(const w_connection_event_peer_address_changed&) = delete;\n    w_connection_event_peer_address_changed(w_connection_event_peer_address_changed&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_peer_address_changed(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around PEER_STREAM_STARTED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_peer_stream_started {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_peer_stream_started() = delete;\n    w_connection_event_peer_stream_started(const w_connection_event_peer_stream_started&) = delete;\n    w_connection_event_peer_stream_started(w_connection_event_peer_stream_started&&) = delete;\n\n    ~w_connection_event_peer_stream_started()\n    {\n        if (_event->PEER_STREAM_STARTED.Stream) {\n            reject_stream();\n        }\n    }\n\n    [[nodiscard]] bool is_unidirectional() const noexcept\n    {\n        return _event->PEER_STREAM_STARTED.Flags & QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL;\n    }\n\n    [[nodiscard]] bool is_bidirectional() const noexcept\n    {\n        return !(_event->PEER_STREAM_STARTED.Flags & QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL);\n    }\n\n    [[nodiscard]] wolf::w_flags<w_stream_open_flag> flags() const noexcept\n    {\n        return static_cast<w_stream_open_flag>(_event->PEER_STREAM_STARTED.Flags);\n    }\n\n    /**\n     * @brief reject the incoming stream.\n     */\n    void reject_stream() const noexcept\n    {\n        if (!_event->PEER_STREAM_STARTED.Stream) {\n            return;\n        }\n\n        internal::w_msquic_api::api()->StreamClose(_event->PEER_STREAM_STARTED.Stream);\n        _event->PEER_STREAM_STARTED.Stream = nullptr;  // to avoid Use-After-Free.\n    }\n\n    /**\n     * @brief accept the incoming stream and set its handler callback.\n     * @param p_callback  event handler callback.\n     */\n    template <typename HandlerF>\n    auto accept_stream(HandlerF&& p_callback) const noexcept\n        -> boost::leaf::result<w_stream>\n    {\n        if (!_event->PEER_STREAM_STARTED.Stream) {\n            return W_FAILURE(std::errc::operation_canceled,\n                             \"stream is already accepted/rejected.\");\n        }\n\n        BOOST_LEAF_AUTO(stream, w_stream::setup_new_raw_stream(\n            _event->PEER_STREAM_STARTED.Stream,\n            std::forward<HandlerF>(p_callback)\n        ));\n\n        _event->PEER_STREAM_STARTED.Stream = nullptr;\n\n        return stream;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_peer_stream_started(internal::w_raw_tag, QUIC_CONNECTION_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around STREAMS_AVAILABLE variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_streams_available {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_streams_available() = delete;\n    w_connection_event_streams_available(const w_connection_event_streams_available&) = delete;\n    w_connection_event_streams_available(w_connection_event_streams_available&&) = delete;\n\n    [[nodiscard]] auto bidirectional_count() const noexcept\n    {\n        return _event->STREAMS_AVAILABLE.BidirectionalCount;\n    }\n\n    [[nodiscard]] auto unidirectional_count() const noexcept\n    {\n        return _event->STREAMS_AVAILABLE.UnidirectionalCount;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_streams_available(internal::w_raw_tag, QUIC_CONNECTION_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around IDEAL_PROCESSOR_CHANGED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_ideal_processor_changed {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_ideal_processor_changed() = delete;\n    w_connection_event_ideal_processor_changed(const w_connection_event_ideal_processor_changed&) = delete;\n    w_connection_event_ideal_processor_changed(w_connection_event_ideal_processor_changed&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_ideal_processor_changed(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around DATAGRAM_STATE_CHANGED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_datagram_state_changed {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_datagram_state_changed() = delete;\n    w_connection_event_datagram_state_changed(const w_connection_event_datagram_state_changed&) = delete;\n    w_connection_event_datagram_state_changed(w_connection_event_datagram_state_changed&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_datagram_state_changed(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around RESUMED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_resumed {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_resumed() = delete;\n    w_connection_event_resumed(const w_connection_event_resumed&) = delete;\n    w_connection_event_resumed(w_connection_event_resumed&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_resumed(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around RESUMPTION_TICKET_RECEIVED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_resumption_ticket_received {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_resumption_ticket_received() = delete;\n    w_connection_event_resumption_ticket_received(const w_connection_event_resumption_ticket_received&) = delete;\n    w_connection_event_resumption_ticket_received(w_connection_event_resumption_ticket_received&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_resumption_ticket_received(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around PEER_CERTIFICATE_RECEIVED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_peer_certificate_received {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_peer_certificate_received() = delete;\n    w_connection_event_peer_certificate_received(const w_connection_event_peer_certificate_received&) = delete;\n    w_connection_event_peer_certificate_received(w_connection_event_peer_certificate_received&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_peer_certificate_received(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around DATAGRAM_RECEIVED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_datagram_received {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_datagram_received() = delete;\n    w_connection_event_datagram_received(const w_connection_event_datagram_received&) = delete;\n    w_connection_event_datagram_received(w_connection_event_datagram_received&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_datagram_received(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around SHUTDOWN_INITIATED_BY_TRANSPORT variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_shutdown_initiated_by_transport {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_shutdown_initiated_by_transport() = delete;\n    w_connection_event_shutdown_initiated_by_transport(const w_connection_event_shutdown_initiated_by_transport&) = delete;\n    w_connection_event_shutdown_initiated_by_transport(w_connection_event_shutdown_initiated_by_transport&&) = delete;\n\n    [[nodiscard]] w_status status() const noexcept\n    {\n        return static_cast<w_status_code>(_event->SHUTDOWN_INITIATED_BY_TRANSPORT.Status);\n    }\n\n    [[nodiscard]] auto error_code() const noexcept\n    {\n        return _event->SHUTDOWN_INITIATED_BY_TRANSPORT.ErrorCode;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_shutdown_initiated_by_transport(internal::w_raw_tag, QUIC_CONNECTION_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around DATAGRAM_SEND_STATE_CHANGED variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_datagram_send_state_changed {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_datagram_send_state_changed() = delete;\n    w_connection_event_datagram_send_state_changed(const w_connection_event_datagram_send_state_changed&) = delete;\n    w_connection_event_datagram_send_state_changed(w_connection_event_datagram_send_state_changed&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_datagram_send_state_changed(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around PEER_NEEDS_STREAMS variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_peer_needs_streams {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_peer_needs_streams() = delete;\n    w_connection_event_peer_needs_streams(const w_connection_event_peer_needs_streams&) = delete;\n    w_connection_event_peer_needs_streams(w_connection_event_peer_needs_streams&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_peer_needs_streams(internal::w_raw_tag, QUIC_CONNECTION_EVENT* /*p_event*/)\n        // : _event(p_event)\n    {}\n\n    // QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around SHUTDOWN_COMPLETE variation of QUIC_CONNECTION_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event_shutdown_complete {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event_shutdown_complete() = delete;\n    w_connection_event_shutdown_complete(const w_connection_event_shutdown_complete&) = delete;\n    w_connection_event_shutdown_complete(w_connection_event_shutdown_complete&&) = delete;\n\n    [[nodiscard]] bool handshake_completed() const noexcept\n    {\n        return _event->SHUTDOWN_COMPLETE.HandshakeCompleted;\n    }\n\n    [[nodiscard]] bool peer_acknowledged_shutdown() const noexcept\n    {\n        return _event->SHUTDOWN_COMPLETE.PeerAcknowledgedShutdown;\n    }\n\n    [[nodiscard]] bool app_close_in_progress() const noexcept\n    {\n        return _event->SHUTDOWN_COMPLETE.AppCloseInProgress;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event_shutdown_complete(internal::w_raw_tag, QUIC_CONNECTION_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around QUIC_CONNECTION_EVENT variant.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_connection_event {\n    friend class internal::w_raw_access;\n\npublic:\n    w_connection_event() = delete;\n    w_connection_event(const w_connection_event&) = delete;\n    w_connection_event(w_connection_event&&) = delete;\n\n    /**\n     * @brief get string name of the underlying event.\n     */\n    [[nodiscard]] auto name() const noexcept -> std::string_view\n    {\n        switch (_event->Type) {\n        case QUIC_CONNECTION_EVENT_CONNECTED:\n            return \"connected\";\n\n        case QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_PEER:\n            return \"shutdown-initiated-by-peer\";\n\n        case QUIC_CONNECTION_EVENT_LOCAL_ADDRESS_CHANGED:\n            return \"local-address-changed\";\n\n        case QUIC_CONNECTION_EVENT_PEER_ADDRESS_CHANGED:\n            return \"peer-address-changed\";\n\n        case QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED:\n            return \"peer-stream-started\";\n\n        case QUIC_CONNECTION_EVENT_STREAMS_AVAILABLE:\n            return \"streams-available\";\n\n        case QUIC_CONNECTION_EVENT_IDEAL_PROCESSOR_CHANGED:\n            return \"ideal-processor-changed\";\n\n        case QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED:\n            return \"datagram-state-changed\";\n\n        case QUIC_CONNECTION_EVENT_RESUMED:\n            return \"resumed\";\n\n        case QUIC_CONNECTION_EVENT_RESUMPTION_TICKET_RECEIVED:\n            return \"resumption-ticket-received\";\n\n        case QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED:\n            return \"peer-certificate-received\";\n\n        case QUIC_CONNECTION_EVENT_DATAGRAM_RECEIVED:\n            return \"datagram-received\";\n\n        case QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT:\n            return \"shutdown-initiated-by-transport\";\n\n        case QUIC_CONNECTION_EVENT_DATAGRAM_SEND_STATE_CHANGED:\n            return \"datagram-send-state-changed\";\n\n        case QUIC_CONNECTION_EVENT_PEER_NEEDS_STREAMS:\n            return \"peer-needs-streams\";\n\n        case QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE:\n            return \"shutdown-complete\";\n        }\n\n        return \"unknown\";\n    }\n\n    /**\n     * @brief visit the variant based on event type.\n     * @param p_visitor  overload to handle different variations of the event instnace.\n     */\n    template <typename F>\n    auto visit(F&& p_visitor)\n    {\n        using accessor = internal::w_raw_access;\n\n        switch (_event->Type) {\n        case QUIC_CONNECTION_EVENT_CONNECTED:\n            return p_visitor(accessor::from_raw<w_connection_event_connected>(_event));\n\n        case QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_PEER:\n            return p_visitor(accessor::from_raw<w_connection_event_shutdown_initiated_by_peer>(_event));\n\n        case QUIC_CONNECTION_EVENT_LOCAL_ADDRESS_CHANGED:\n            return p_visitor(accessor::from_raw<w_connection_event_local_address_changed>(_event));\n\n        case QUIC_CONNECTION_EVENT_PEER_ADDRESS_CHANGED:\n            return p_visitor(accessor::from_raw<w_connection_event_peer_address_changed>(_event));\n\n        case QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED:\n            return p_visitor(accessor::from_raw<w_connection_event_peer_stream_started>(_event));\n\n        case QUIC_CONNECTION_EVENT_STREAMS_AVAILABLE:\n            return p_visitor(accessor::from_raw<w_connection_event_streams_available>(_event));\n\n        case QUIC_CONNECTION_EVENT_IDEAL_PROCESSOR_CHANGED:\n            return p_visitor(accessor::from_raw<w_connection_event_ideal_processor_changed>(_event));\n\n        case QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED:\n            return p_visitor(accessor::from_raw<w_connection_event_datagram_state_changed>(_event));\n\n        case QUIC_CONNECTION_EVENT_RESUMED:\n            return p_visitor(accessor::from_raw<w_connection_event_resumed>(_event));\n\n        case QUIC_CONNECTION_EVENT_RESUMPTION_TICKET_RECEIVED:\n            return p_visitor(accessor::from_raw<w_connection_event_resumption_ticket_received>(_event));\n\n        case QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED:\n            return p_visitor(accessor::from_raw<w_connection_event_peer_certificate_received>(_event));\n\n        case QUIC_CONNECTION_EVENT_DATAGRAM_RECEIVED:\n            return p_visitor(accessor::from_raw<w_connection_event_datagram_received>(_event));\n\n        case QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT:\n            return p_visitor(accessor::from_raw<w_connection_event_shutdown_initiated_by_transport>(_event));\n\n        case QUIC_CONNECTION_EVENT_DATAGRAM_SEND_STATE_CHANGED:\n            return p_visitor(accessor::from_raw<w_connection_event_datagram_send_state_changed>(_event));\n\n        case QUIC_CONNECTION_EVENT_PEER_NEEDS_STREAMS:\n            return p_visitor(accessor::from_raw<w_connection_event_peer_needs_streams>(_event));\n\n        case QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE:\n            return p_visitor(accessor::from_raw<w_connection_event_shutdown_complete>(_event));\n        }\n\n        return p_visitor(std::monostate{});\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_connection_event(internal::w_raw_tag, QUIC_CONNECTION_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_CONNECTION_EVENT* _event = nullptr;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/events/w_listener_event.cpp",
    "content": "#include \"stream/quic/events/w_listener_event.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/events/w_listener_event.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/internal/w_msquic_api.hpp\"\n#include \"stream/quic/datatypes/w_new_connection_info.hpp\"\n#include \"stream/quic/handles/w_connection.hpp\"\n\n#include <msquic.h>\n\n// NOTE windows.h must be included after msquic.h\n//      due to some declaration issues.\n#include \"wolf.hpp\"\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief Wrapper of NEW_CONNECTION variation of QUIC_LISTENER_EVENT.\n *\n * There are access/proxy methods to access each field.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_listener_event_new_connection {\n    friend class internal::w_raw_access;\n\npublic:\n    w_listener_event_new_connection() = delete;\n    w_listener_event_new_connection(const w_listener_event_new_connection&) = delete;\n    w_listener_event_new_connection(w_listener_event_new_connection&&) = delete;\n\n    ~w_listener_event_new_connection()\n    {\n        // make sure to close connection if still afloating\n        // to avoid leak/deadlock/crash.\n        if (_event->NEW_CONNECTION.Connection) {\n            reject_connection();\n        }\n    }\n\n    /**\n     * @brief get the new connection's info.\n     */\n    [[nodiscard]] w_new_connection_info connection_info() const noexcept\n    {\n        return internal::w_raw_access::from_raw<w_new_connection_info>(*_event->NEW_CONNECTION.Info);\n    }\n\n    /**\n     * @brief reject and close the incoming connection handle.\n     */\n    void reject_connection() noexcept\n    {\n        if (!_event->NEW_CONNECTION.Connection) {\n            return;\n        }\n\n        internal::w_msquic_api::api()->ConnectionClose(_event->NEW_CONNECTION.Connection);\n        _event->NEW_CONNECTION.Connection = nullptr;  // to avoid Use-After-Free.\n    }\n\n    /**\n     * @brief accept and setup the new connection handle.\n     *\n     * @param p_config    configuration to set.\n     * @param p_callback  event handler callback.\n     * @return success or error.\n     */\n    auto accept_connection(w_configuration& p_config, w_connection::callback_type p_callback) noexcept\n        -> boost::leaf::result<w_connection>\n    {\n        if (!_event->NEW_CONNECTION.Connection) {\n            return W_FAILURE(std::errc::operation_canceled,\n                             \"connection is already accepted or rejected.\");\n        }\n\n        BOOST_LEAF_AUTO(conn, w_connection::setup_new_raw_connection(\n            _event->NEW_CONNECTION.Connection,\n            p_config,\n            std::move(p_callback)\n        ));\n\n        _event->NEW_CONNECTION.Connection = nullptr;\n\n        return conn;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_listener_event_new_connection(internal::w_raw_tag, QUIC_LISTENER_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_LISTENER_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper of STOP_COMPLETE variation of QUIC_LISTENER_EVENT.\n *\n * There are access/proxy methods to access each field.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_listener_event_stop_complete {\n    friend class internal::w_raw_access;\n\npublic:\n    w_listener_event_stop_complete() = delete;\n    w_listener_event_stop_complete(const w_listener_event_stop_complete&) = delete;\n    w_listener_event_stop_complete(w_listener_event_stop_complete&&) = delete;\n\n    /**\n     * @brief whether the app close is in progress.\n     */\n    [[nodiscard]] bool app_close_in_progress() const noexcept\n    {\n        return _event->STOP_COMPLETE.AppCloseInProgress;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_listener_event_stop_complete(internal::w_raw_tag, QUIC_LISTENER_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_LISTENER_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around QUIC_LISTENER_EVENT variant.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_listener_event {\n    friend class internal::w_raw_access;\n\npublic:\n    w_listener_event() = delete;\n    w_listener_event(const w_listener_event&) = delete;\n    w_listener_event(w_listener_event&&) = delete;\n\n    /**\n     * @brief get string name of the underlying event.\n     */\n    [[nodiscard]] auto name() const noexcept -> std::string_view\n    {\n        switch (_event->Type) {\n        case QUIC_LISTENER_EVENT_NEW_CONNECTION:\n            return \"new-connection\";\n\n        case QUIC_LISTENER_EVENT_STOP_COMPLETE:\n            return \"stop-complete\";\n        }\n\n        return \"unknown\";\n    }\n\n    /**\n     * @brief visit the variant based on event type.\n     * @param p_visitor  overload to handle different variations of the event instnace.\n     */\n    template <typename F>\n    auto visit(F&& p_visitor)\n    {\n        switch (_event->Type) {\n        case QUIC_LISTENER_EVENT_NEW_CONNECTION:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_listener_event_new_connection>(_event)\n            );\n        case QUIC_LISTENER_EVENT_STOP_COMPLETE:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_listener_event_stop_complete>(_event)\n            );\n        }\n\n        return p_visitor(std::monostate{});\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_listener_event(internal::w_raw_tag, QUIC_LISTENER_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_LISTENER_EVENT* _event = nullptr;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/events/w_stream_event.cpp",
    "content": "#include \"stream/quic/events/w_stream_event.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/events/w_stream_event.hpp",
    "content": "#pragma once\n\n#include \"system/w_flags.hpp\"\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/datatypes/common_flags.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n\n#include <msquic.h>\n\n#include <span>\n#include <ranges>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief Wrapper around START_COMPLETE variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_start_complete {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_start_complete() = delete;\n    w_stream_event_start_complete(const w_stream_event_start_complete&) = delete;\n    w_stream_event_start_complete(w_stream_event_start_complete&&) = delete;\n\n    [[nodiscard]] w_status status() const noexcept\n    {\n        return static_cast<w_status_code>(_event->START_COMPLETE.Status);\n    }\n\n    [[nodiscard]] auto id() const noexcept\n    {\n        return _event->START_COMPLETE.ID;\n    }\n\n    [[nodiscard]] bool peer_accepted() const noexcept\n    {\n        return _event->START_COMPLETE.PeerAccepted;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_start_complete(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around RECEIVE variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_receive {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_receive() = delete;\n    w_stream_event_receive(const w_stream_event_receive&) = delete;\n    w_stream_event_receive(w_stream_event_receive&&) = delete;\n\n    [[nodiscard]] auto total_buffer_length() const noexcept\n    {\n        return _event->RECEIVE.TotalBufferLength;\n    }\n\n    [[nodiscard]] auto buffers() const noexcept\n    {\n        return std::span(_event->RECEIVE.Buffers, _event->RECEIVE.BufferCount)\n             | std::ranges::views::transform([](const QUIC_BUFFER& buf) {\n                 return std::span(buf.Buffer, buf.Length);\n               });\n    }\n\n    [[nodiscard]] wolf::w_flags<w_receive_flag> flags() const noexcept\n    {\n        return static_cast<w_receive_flag>(_event->RECEIVE.Flags);\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_receive(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around SEND_COMPLETE variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_send_complete {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_send_complete() = delete;\n    w_stream_event_send_complete(const w_stream_event_send_complete&) = delete;\n    w_stream_event_send_complete(w_stream_event_send_complete&&) = delete;\n\n    [[nodiscard]] bool canceled() const noexcept\n    {\n        return _event->SEND_COMPLETE.Canceled;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_send_complete(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around PEER_SEND_SHUTDOWN variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_peer_send_shutdown {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_peer_send_shutdown() = delete;\n    w_stream_event_peer_send_shutdown(const w_stream_event_peer_send_shutdown&) = delete;\n    w_stream_event_peer_send_shutdown(w_stream_event_peer_send_shutdown&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_peer_send_shutdown(internal::w_raw_tag, QUIC_STREAM_EVENT* /*p_event*/)\n        // : _event(p_event) // unused\n    {}\n\n    // QUIC_STREAM_EVENT* _event = nullptr; // unused\n};\n\n/**\n * @brief Wrapper around PEER_SEND_ABORTED variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_peer_send_aborted {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_peer_send_aborted() = delete;\n    w_stream_event_peer_send_aborted(const w_stream_event_peer_send_aborted&) = delete;\n    w_stream_event_peer_send_aborted(w_stream_event_peer_send_aborted&&) = delete;\n\n    [[nodiscard]] auto error_code() const noexcept\n    {\n        return _event->PEER_SEND_ABORTED.ErrorCode;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_peer_send_aborted(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around PEER_RECEIVE_ABORTED variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_peer_receive_aborted {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_peer_receive_aborted() = delete;\n    w_stream_event_peer_receive_aborted(const w_stream_event_peer_receive_aborted&) = delete;\n    w_stream_event_peer_receive_aborted(w_stream_event_peer_receive_aborted&&) = delete;\n\n    [[nodiscard]] auto error_code() const noexcept\n    {\n        return _event->PEER_RECEIVE_ABORTED.ErrorCode;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_peer_receive_aborted(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around SEND_SHUTDOWN_COMPLETE variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_send_shutdown_complete {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_send_shutdown_complete() = delete;\n    w_stream_event_send_shutdown_complete(const w_stream_event_send_shutdown_complete&) = delete;\n    w_stream_event_send_shutdown_complete(w_stream_event_send_shutdown_complete&&) = delete;\n\n    [[nodiscard]] bool graceful() const noexcept\n    {\n        return _event->SEND_SHUTDOWN_COMPLETE.Graceful;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_send_shutdown_complete(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around SHUTDOWN_COMPLETE variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_shutdown_complete {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_shutdown_complete() = delete;\n    w_stream_event_shutdown_complete(const w_stream_event_shutdown_complete&) = delete;\n    w_stream_event_shutdown_complete(w_stream_event_shutdown_complete&&) = delete;\n\n    [[nodiscard]] bool connection_shutdown() const noexcept\n    {\n        return _event->SHUTDOWN_COMPLETE.ConnectionShutdown;\n    }\n\n    [[nodiscard]] bool app_close_in_progress() const noexcept\n    {\n        return _event->SHUTDOWN_COMPLETE.AppCloseInProgress;\n    }\n\n    [[nodiscard]] bool connection_shutdown_by_app() const noexcept\n    {\n        return _event->SHUTDOWN_COMPLETE.ConnectionShutdownByApp;\n    }\n\n    [[nodiscard]] bool connection_closed_remotely() const noexcept\n    {\n        return _event->SHUTDOWN_COMPLETE.ConnectionClosedRemotely;\n    }\n\n    [[nodiscard]] auto connection_error_code() const noexcept\n    {\n        return _event->SHUTDOWN_COMPLETE.ConnectionErrorCode;\n    }\n\n    [[nodiscard]] w_status connection_close_status() const noexcept\n    {\n        return static_cast<w_status_code>(_event->SHUTDOWN_COMPLETE.ConnectionCloseStatus);\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_shutdown_complete(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around IDEAL_SEND_BUFFER_SIZE variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_ideal_send_buffer_size {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_ideal_send_buffer_size() = delete;\n    w_stream_event_ideal_send_buffer_size(const w_stream_event_ideal_send_buffer_size&) = delete;\n    w_stream_event_ideal_send_buffer_size(w_stream_event_ideal_send_buffer_size&&) = delete;\n\n    [[nodiscard]] std::size_t byte_count() const noexcept\n    {\n        return _event->IDEAL_SEND_BUFFER_SIZE.ByteCount;\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_ideal_send_buffer_size(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n/**\n * @brief Wrapper around PEER_ACCEPTED variation of QUIC_STREAM_EVENT.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event_peer_accepted {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event_peer_accepted() = delete;\n    w_stream_event_peer_accepted(const w_stream_event_peer_accepted&) = delete;\n    w_stream_event_peer_accepted(w_stream_event_peer_accepted&&) = delete;\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event_peer_accepted(internal::w_raw_tag, QUIC_STREAM_EVENT* /*p_event*/)\n        // : _event(p_event) // unused\n    {}\n\n    // QUIC_STREAM_EVENT* _event = nullptr; // unused\n};\n\n/**\n * @brief Wrapper around QUIC_STREAM_EVENT variant.\n *\n * @note This class is non-owning and also is not move or copy-able,\n *       but only referencible.\n *       please refer to its provider for lifetime guarantees.\n */\nclass W_API w_stream_event {\n    friend class internal::w_raw_access;\n\npublic:\n    w_stream_event() = delete;\n    w_stream_event(const w_stream_event&) = delete;\n    w_stream_event(w_stream_event&&) = delete;\n\n    /**\n     * @brief get string name of the underlying event.\n     */\n    [[nodiscard]] auto name() const noexcept -> std::string_view\n    {\n        switch (_event->Type) {\n        case QUIC_STREAM_EVENT_START_COMPLETE:\n            return \"start-complete\";\n\n        case QUIC_STREAM_EVENT_RECEIVE:\n            return \"receive\";\n\n        case QUIC_STREAM_EVENT_SEND_COMPLETE:\n            return \"send-complete\";\n\n        case QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN:\n            return \"peer-send-shutdown\";\n\n        case QUIC_STREAM_EVENT_PEER_SEND_ABORTED:\n            return \"peer-send-aborted\";\n\n        case QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED:\n            return \"peer-receive-aborted\";\n\n        case QUIC_STREAM_EVENT_SEND_SHUTDOWN_COMPLETE:\n            return \"send-shutdown-complete\";\n\n        case QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE:\n            return \"shutdown-complete\";\n\n        case QUIC_STREAM_EVENT_IDEAL_SEND_BUFFER_SIZE:\n            return \"ideal-send-buffer-size\";\n\n        case QUIC_STREAM_EVENT_PEER_ACCEPTED:\n            return \"peer-accepted\";\n        }\n\n        return \"unknown\";\n    }\n\n    /**\n     * @brief visit the variant based on event type.\n     * @param p_visitor  overload to handle different variations of the event instnace.\n     */\n    template <typename F>\n    auto visit(F&& p_visitor)\n    {\n        switch (_event->Type) {\n        case QUIC_STREAM_EVENT_START_COMPLETE:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_start_complete>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_RECEIVE:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_receive>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_SEND_COMPLETE:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_send_complete>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_peer_send_shutdown>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_PEER_SEND_ABORTED:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_peer_send_shutdown>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_peer_receive_aborted>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_SEND_SHUTDOWN_COMPLETE:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_send_shutdown_complete>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_shutdown_complete>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_IDEAL_SEND_BUFFER_SIZE:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_ideal_send_buffer_size>(_event)\n            );\n\n        case QUIC_STREAM_EVENT_PEER_ACCEPTED:\n            return p_visitor(\n                internal::w_raw_access::from_raw<w_stream_event_peer_accepted>(_event)\n            );\n        }\n\n        return p_visitor(std::monostate{});\n    }\n\nprivate:\n    /**\n     * @brief wrap the given raw event as non-owning.\n     * @param p_event  pointer to event.\n     */\n    w_stream_event(internal::w_raw_tag, QUIC_STREAM_EVENT* p_event)\n        : _event(p_event)\n    {}\n\n    QUIC_STREAM_EVENT* _event = nullptr;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_configuration.cpp",
    "content": "#include \"stream/quic/handles/w_configuration.hpp\"\n\n#include \"stream/quic/internal/w_msquic_api.hpp\"\n\n#include \"wolf.hpp\"\n\nnamespace wolf::stream::quic {\n\nauto w_configuration::open(w_registration& p_reg,\n                           const w_settings& p_settings,\n                           w_alpn_view p_alpn) noexcept\n    -> boost::leaf::result<w_configuration>\n{\n    HQUIC handle = nullptr;\n    auto api = internal::w_msquic_api::api();\n\n    auto reg_raw = internal::w_raw_access::raw(p_reg);\n    if (!reg_raw) {\n        return W_FAILURE(std::errc::invalid_argument, \"given registration is invalid.\");\n    }\n\n    auto settings = internal::w_raw_access::raw(p_settings);\n\n    auto alpn = QUIC_BUFFER{\n        .Length = static_cast<unsigned int>(p_alpn.size()),\n        .Buffer = p_alpn.data()\n    };\n\n    w_status status = api->ConfigurationOpen(reg_raw,\n                                             &alpn, 1,\n                                             &settings, sizeof(settings),\n                                             nullptr,\n                                             &handle);\n    if (status.failed()) {\n        return W_FAILURE(\n            std::errc::operation_canceled,\n            wolf::format(\"couldn't open configuration: {}\", status_to_str(status)));\n    }\n\n    return w_configuration(internal::w_raw_tag{}, handle);\n}\n\nauto w_configuration::open(w_registration& p_reg,\n                           const w_settings& p_settings,\n                           w_alpn_view p_alpn,\n                           const w_credential_config& p_cred_conf) noexcept\n    -> boost::leaf::result<w_configuration>\n{\n    BOOST_LEAF_AUTO(ret, open(p_reg, p_settings, p_alpn));\n    auto status = ret.load_credential(p_cred_conf);\n    if (status.failed()) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         wolf::format(\"couldn't load config credentials: {}\", status_to_str(status)));\n    }\n    return ret;\n}\n\nw_status wolf::stream::quic::w_configuration::load_credential(const w_credential_config& p_creds_config)\n{\n    if (!_handle) {\n        return w_status_code::InvalidState;\n    }\n\n    auto api = internal::w_msquic_api::api();\n    auto creds_config_raw = internal::w_raw_access::raw(p_creds_config);\n    return api->ConfigurationLoadCredential(_handle, creds_config_raw);\n}\n\nvoid w_configuration::close()\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n    api->ConfigurationClose(_handle);\n    _handle = nullptr;\n}\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_configuration.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n#include \"stream/quic/datatypes/w_settings.hpp\"\n#include \"stream/quic/datatypes/w_alpn.hpp\"\n#include \"stream/quic/datatypes/w_credential_config.hpp\"\n#include \"stream/quic/handles/w_registration.hpp\"\n\n#include <boost/leaf.hpp>\n#include <msquic.h>\n\n#include <span>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief The wrapper of configuration concept of msquic.\n *\n * The configuration is quite bound to the registration,\n * it must be closed or destructed before registration being closed/destructed.\n *\n * @note make sure your registration handle outlives the configuration handle,\n *       or you might face deadlocks.\n */\nclass W_API w_configuration {\n    friend internal::w_raw_access;\n\npublic:\n    /**\n     * @brief constructs an empty handle.\n     * @note use static factory function `open` to create valid handle.\n     */\n    w_configuration() {}\n\n    w_configuration(const w_configuration&) = delete;\n    w_configuration(w_configuration&& p_other) noexcept\n        : _handle(std::exchange(p_other._handle, nullptr))\n    {}\n\n    w_configuration& operator=(const w_configuration&) = delete;\n    w_configuration& operator=(w_configuration&& p_other) noexcept\n    {\n        std::swap(_handle, p_other._handle);\n        return *this;\n    }\n\n    ~w_configuration() { close(); }\n\n    /**\n     * @brief whether the handle is open/valid or not.\n     */\n    [[nodiscard]] bool is_valid() const noexcept { return _handle; }\n\n    /**\n     * @brief open/create a configuration with given registration, settings and alpn.\n     * @param p_reg      registration handle.\n     * @param p_settings single configuration settings.\n     * @param p_alpn     single application-layer protocol negotiation.\n     * @return an instance of w_configuration on success, otherwise error.\n     */\n    [[nodiscard]] static auto open(w_registration& p_reg,\n                                   const w_settings& p_settings,\n                                   w_alpn_view p_alpn) noexcept\n        -> boost::leaf::result<w_configuration>;\n\n    /**\n     * @brief open/create a configuration with given registration, settings,\n     *        alpn and credential config.\n     * @param p_reg         registration handle.\n     * @param p_settings    single configuration settings.\n     * @param p_alpn        single application-layer protocol negotiation.\n     * @param p_cred_config credential config.\n     * @return an instance of w_configuration on success, otherwise error.\n     */\n    [[nodiscard]] static auto open(w_registration& p_reg,\n                                   const w_settings& p_settings,\n                                   w_alpn_view p_alpn,\n                                   const w_credential_config& p_cred_conf) noexcept\n        -> boost::leaf::result<w_configuration>;\n\n    /**\n     * @brief load the given certificate credential into the configuration.\n     * @param p_creds_config  certificate credential config.\n     * @return status whether it succeeded or failed.\n     */\n    w_status load_credential(const w_credential_config& p_creds_config);\n\n    /**\n     * @brief close the configuration handle.\n     */\n    void close();\n\nprivate:\n    auto raw() noexcept { return _handle; }\n    auto raw() const noexcept { return _handle; }\n\n    explicit w_configuration(internal::w_raw_tag, HQUIC p_handle) noexcept\n        : _handle(p_handle)\n    {}\n\n    HQUIC _handle = nullptr;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_connection.cpp",
    "content": "#include \"stream/quic/handles/w_connection.hpp\"\n#include \"stream/quic/events/w_connection_event.hpp\"\n#include \"stream/quic/internal/w_msquic_api.hpp\"\n\n// NOTE: this header must be included after msquic.h\n//       or there would be a redefinition error.\n#include \"wolf.hpp\"\n\nnamespace wolf::stream::quic {\n\nQUIC_STATUS w_connection::internal_raw_callback(HQUIC p_connection_raw,\n                                                void* p_context_raw,\n                                                QUIC_CONNECTION_EVENT* p_event_raw)\n{\n    if (!p_context_raw) {\n        return QUIC_STATUS_INTERNAL_ERROR;\n    }\n\n    auto context = static_cast<context_bundle*>(p_context_raw);\n\n    auto connection = w_connection(internal::w_raw_tag{}, p_connection_raw);\n    auto event = internal::w_raw_access::from_raw<w_connection_event>(p_event_raw);\n\n    w_status status = context->callback(connection, event);\n\n    if (p_event_raw->Type == QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE) {\n        context->running = false;\n        // not running anymore, thus no longer requires to be held for callback.\n        --context->refcount;\n    }\n\n    return status;\n}\n\nbool w_connection::is_running() const noexcept\n{\n    if (!_handle) {\n        return false;\n    }\n\n    auto api = internal::w_msquic_api::api();\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    return context->running;\n}\n\nauto w_connection::open(w_registration& p_reg, callback_type p_callback) noexcept\n    -> boost::leaf::result<w_connection>\n{\n    HQUIC handle = nullptr;\n\n    auto api = internal::w_msquic_api::api();\n\n    auto reg_raw = internal::w_raw_access::raw(p_reg);\n    if (!reg_raw) {\n        return W_FAILURE(std::errc::invalid_argument,\n                         \"given registration is not valid.\");\n    }\n\n    auto [context_ptr, callback_ptr] = make_context_callback_ptrs(std::move(p_callback));\n    if (!context_ptr || !callback_ptr) {\n        return W_FAILURE(std::errc::not_enough_memory,\n                         \"couldn't allocate for callback context.\");\n    }\n\n    w_status status = api->ConnectionOpen(\n        reg_raw,\n        (QUIC_CONNECTION_CALLBACK_HANDLER)callback_ptr,\n        (void*)context_ptr,\n        &handle\n    );\n    if (status.failed()) {\n        delete context_ptr;\n        return W_FAILURE(std::errc::operation_canceled,\n                         wolf::format(\"couldn't open/create connection: {}\", status_to_str(status)));\n    }\n\n    return w_connection(internal::w_raw_tag{}, handle);\n}\n\nauto w_connection::set_callback(callback_type p_callback) -> boost::leaf::result<void>\n{\n    if (!_handle) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"connection is closed/destroyed.\");\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n\n    if (!context) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"connection is in invalid state.\");\n    }\n\n    if (context->running) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"can't set callback when connection is active/running.\");\n    }\n\n    context->callback = std::move(p_callback);\n\n    return {};\n}\n\nw_status w_connection::start(w_configuration& p_config, const char* p_host, std::uint16_t p_port)\n{\n    if (!_handle) {\n        return w_status_code::InvalidState;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    context_bundle* context = static_cast<context_bundle*>(api->GetContext(_handle));\n    if (!context || context->closing || context->running) {\n        return w_status_code::InvalidState;\n    }\n\n    auto config_raw = internal::w_raw_access::raw(p_config);\n\n    w_status status = api->ConnectionStart(\n        _handle,\n        config_raw,\n        QUIC_ADDRESS_FAMILY_UNSPEC,\n        p_host,\n        p_port\n    );\n\n    if (status.failed()) {\n        return status;\n    }\n\n    context->running = true;\n    // account one more for running connections to\n    // be passed into the callback.\n    ++context->refcount;\n\n    return status;\n}\n\nvoid w_connection::shutdown(wolf::w_flags<w_connection_shutdown_flag> p_flags,\n                            std::size_t p_error_code)\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    if (!context || !context->running) {\n        return;\n    }\n\n    const auto flags = static_cast<QUIC_CONNECTION_SHUTDOWN_FLAGS>(p_flags.to_underlying());\n\n    api->ConnectionShutdown(_handle, flags, p_error_code);\n}\n\nvoid w_connection::close()\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    if (!context || context->closing) {\n        return;\n    }\n\n    if (--context->refcount > 0) {\n        return;\n    }\n\n    // makes sure if callback calls close,\n    // it wouldn't result in reentrancy in msquic api.\n    context->closing = true;\n\n    api->ConnectionClose(_handle);\n    _handle = nullptr;\n    delete context;\n}\n\nauto w_connection::setup_new_raw_connection(HQUIC p_conn_raw,\n                                            w_configuration& p_config,\n                                            callback_type p_callback) noexcept\n    -> boost::leaf::result<w_connection>\n{\n    auto api = internal::w_msquic_api::api();\n    auto config_raw = internal::w_raw_access::raw(p_config);\n    if (!config_raw) {\n        return W_FAILURE(std::errc::invalid_argument, \"given config is closed or invalid.\");\n    }\n\n    w_status status = api->ConnectionSetConfiguration(p_conn_raw, config_raw);\n    if (status.failed()) {\n        auto err_str = wolf::format(\"couldn't set the configuration on the connection: {}\",\n                                    status_to_str(status));\n        return W_FAILURE(std::errc::operation_canceled, err_str);\n    }\n\n    auto [context_ptr, callback_ptr] = make_context_callback_ptrs(std::move(p_callback));\n    if (!context_ptr) {\n        return W_FAILURE(std::errc::not_enough_memory,\n                         \"couldn't allocate for connection callback context.\");\n    }\n\n    api->SetCallbackHandler(\n        p_conn_raw,\n        (QUIC_CONNECTION_CALLBACK_HANDLER)callback_ptr,\n        context_ptr\n    );\n\n    context_ptr->running = true;\n    ++context_ptr->refcount;\n\n    return w_connection(internal::w_raw_tag{}, p_conn_raw);\n}\n\nw_connection::w_connection(internal::w_raw_tag, HQUIC p_handle) noexcept\n    : _handle(p_handle)\n{\n    auto api = internal::w_msquic_api::api();\n    auto context = static_cast<context_bundle*>(api->GetContext(p_handle));\n    ++context->refcount;\n}\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_connection.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n#include \"stream/quic/handles/w_configuration.hpp\"\n#include \"stream/quic/handles/w_registration.hpp\"\n\n#include <boost/leaf.hpp>\n#include <msquic.h>\n\n#include <atomic>\n#include <span>\n#include <tuple>\n#include <mutex>\n\nnamespace wolf::stream::quic {\n\nclass w_connection_event;\nclass w_listener_event_new_connection;\n\n/**\n * @brief The wrapper of connection handle of msquic.\n */\nclass W_API w_connection {\n    friend class internal::w_raw_access;\n    friend class w_listener_event_new_connection;\n\npublic:\n    using callback_type = std::function<w_status(w_connection&, w_connection_event&)>;\n\nprivate:\n    using raw_callback_type = QUIC_STATUS(HQUIC, void*, QUIC_CONNECTION_EVENT*);\n\n    struct context_bundle {\n        callback_type callback;\n        std::atomic<bool> running = false;\n        std::atomic<int> refcount = 0;\n        bool closing = false; // to avoid double free in reentrancy of close() in callback.\n    };\n\n    static QUIC_STATUS internal_raw_callback(HQUIC p_connection_raw,\n                                             void* p_context_raw,\n                                             QUIC_CONNECTION_EVENT* p_event_raw);\n\npublic:\n    /**\n     * @brief constructs an empty handle.\n     * @note use static factory function `open` to create a valid handle.\n     */\n    w_connection() {}\n\n    w_connection(const w_connection&) = delete;\n    w_connection(w_connection&& p_other) noexcept\n        : _handle(std::exchange(p_other._handle, nullptr))\n    {}\n\n    w_connection& operator=(const w_connection&) = delete;\n    w_connection& operator=(w_connection&& p_other) noexcept\n    {\n        std::swap(_handle, p_other._handle);\n        return *this;\n    }\n\n    ~w_connection() { close(); }\n\n    /**\n     * @brief whether the handle is open/valid or not.\n     */\n    [[nodiscard]] bool is_valid() const noexcept { return _handle; }\n\n    /**\n     * @brief whether it has been started and running.\n     */\n    [[nodiscard]] bool is_running() const noexcept;\n\n    /**\n     * @brief open/create a connection.\n     * @param p_reg       registration (execution context).\n     * @param p_callback  connection callback.\n     * @return a connection instance on success.\n     */\n    [[nodiscard]] static auto open(w_registration& p_reg, callback_type p_callback) noexcept\n        -> boost::leaf::result<w_connection>;\n\n    /**\n     * @brief set callback.\n     * @param p_callback  connection callback.\n     * @return success or failure.\n     */\n    auto set_callback(callback_type p_callback) -> boost::leaf::result<void>;\n\n    /**\n     * @brief start the connection to connect.\n     * @param p_config  the configuration to use for connection.\n     * @param p_host    the host to connect to.\n     * @param p_alpn    the port to connect to.\n     * @return status of success or failure.\n     */\n    w_status start(w_configuration& p_config, const char* p_host, std::uint16_t p_port);\n\n    /**\n     * @brief shutdown the connection.\n     *\n     * This is a non-blocking call, completion will be notified\n     * by shutdown_complete event in callback.\n     */\n    void shutdown(wolf::w_flags<w_connection_shutdown_flag> p_flags = w_connection_shutdown_flag::None,\n                  std::size_t p_error_code = 0);\n\n    /**\n     * @brief close the connection handle.\n     *\n     * after this the instance will be unusable.\n     */\n    void close();\n\nprivate:\n    /**\n     * @brief setup the new raw connection created by msquic.\n     * @param p_conn_raw  raw connection handle.\n     * @param p_config    configuration to associate with.\n     * @param p_callback  event handler callback.\n     * @return status of whether succeeded or not.\n     */\n    [[nodiscard]] static auto setup_new_raw_connection(HQUIC p_conn_raw,\n                                                       w_configuration& p_config,\n                                                       callback_type p_callback) noexcept\n        -> boost::leaf::result<w_connection>;\n\n    template <typename HandlerF>\n    [[nodiscard]] static auto make_context_callback_ptrs(HandlerF&& p_callback)\n        -> std::pair<context_bundle*, QUIC_CONNECTION_CALLBACK_HANDLER>\n    {\n        return {\n            new context_bundle{ .callback = std::forward<HandlerF>(p_callback) },\n            internal_raw_callback\n        };\n    }\n\n    auto raw() noexcept { return _handle; }\n    auto raw() const noexcept { return _handle; }\n\n    explicit w_connection(internal::w_raw_tag, HQUIC p_handle) noexcept;\n\n    HQUIC _handle = nullptr;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_listener.cpp",
    "content": "#include \"stream/quic/handles/w_listener.hpp\"\n#include \"stream/quic/internal/w_msquic_api.hpp\"\n\n// NOTE: this header must be included after msquic.h\n//       or there would be a redefinition error.\n#include \"wolf.hpp\"\n\nnamespace wolf::stream::quic {\n\nQUIC_STATUS w_listener::internal_raw_callback(HQUIC p_listener_raw,\n                                              void* p_context_raw,\n                                              QUIC_LISTENER_EVENT* p_event_raw)\n{\n    if (!p_context_raw) {\n        return QUIC_STATUS_INTERNAL_ERROR;\n    }\n\n    auto context = static_cast<context_bundle*>(p_context_raw);\n\n    auto listener = w_listener(internal::w_raw_tag{}, p_listener_raw);\n    auto event = internal::w_raw_access::from_raw<w_listener_event>(p_event_raw);\n\n    w_status status = context->callback(listener, event);\n\n    if (p_event_raw->Type == QUIC_LISTENER_EVENT_STOP_COMPLETE) {\n        context->running = false;\n        --context->refcount;\n    }\n\n    return status;\n}\n\nbool w_listener::is_running() const noexcept\n{\n    if (!_handle) {\n        return false;\n    }\n\n    auto api = internal::w_msquic_api::api();\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    return context->running;\n}\n\nauto w_listener::open(w_registration& p_reg, callback_type p_callback) noexcept\n    -> boost::leaf::result<w_listener>\n{\n    HQUIC handle = nullptr;\n\n    auto api = internal::w_msquic_api::api();\n\n    auto reg_raw = internal::w_raw_access::raw(p_reg);\n    if (!reg_raw) {\n        return W_FAILURE(std::errc::invalid_argument,\n                         \"given registration is not valid.\");\n    }\n\n    auto context_ptr = new context_bundle{};\n    if (!context_ptr) {\n        return W_FAILURE(std::errc::not_enough_memory,\n                         \"couldn't allocate for callback context.\");\n    }\n\n    context_ptr->callback = std::move(p_callback);\n\n    w_status status = api->ListenerOpen(reg_raw,\n                                        (QUIC_LISTENER_CALLBACK_HANDLER)internal_raw_callback,\n                                        (void*)context_ptr,\n                                        &handle);\n    if (status.failed()) {\n        delete context_ptr;\n        return W_FAILURE(std::errc::operation_canceled,\n                         wolf::format(\"couldn't open/create listener: {}\", status_to_str(status)));\n    }\n\n    return w_listener(internal::w_raw_tag{}, handle);\n}\n\nauto w_listener::set_callback(callback_type p_callback) -> boost::leaf::result<void>\n{\n    if (!_handle) {\n        return W_FAILURE(std::errc::operation_canceled, \"listener is closed/destroyed.\");\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n\n    if (!context) {\n        return W_FAILURE(std::errc::operation_canceled, \"listener is in invalid state.\");\n    }\n\n    if (context->running) {\n        return W_FAILURE(std::errc::operation_canceled, \"listener is running.\");\n    }\n\n    context->callback = std::move(p_callback);\n\n    return {};\n}\n\nw_status w_listener::start(const w_address& p_address, w_alpn_view p_alpn)\n{\n    if (!_handle) {\n        return w_status_code::InvalidState;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    context_bundle* context = static_cast<context_bundle*>(api->GetContext(_handle));\n    if (!context) {\n        return w_status_code::InvalidState;\n    }\n\n    auto address_raw = internal::w_raw_access::raw(p_address);\n    auto alpn  = QUIC_BUFFER{\n        .Length = (unsigned int)p_alpn.size(),\n        .Buffer = p_alpn.data()\n    };\n\n    w_status status = api->ListenerStart(_handle, &alpn, 1, address_raw);\n    if (status.failed()) {\n        return status;\n    }\n\n    context->running = true;\n    ++context->refcount;\n\n    return status;\n}\n\nvoid w_listener::stop()\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n\n    // if the context doesn't exist, it's already closed.\n    if (!context || !context->running) {\n        return;\n    }\n\n    api->ListenerStop(_handle);\n}\n\nvoid w_listener::close()\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    if (!context || context->closed) {\n        return;\n    }\n\n    if (--context->refcount > 0) {\n        return;\n    }\n\n    // making sure if callback calls close,\n    // it wouldn't result in reentrancy in msquic api.\n    context->closed = true;\n\n    api->ListenerClose(_handle);\n    _handle = nullptr;\n    delete context;\n}\n\nw_listener::w_listener(internal::w_raw_tag, HQUIC p_handle) noexcept\n    : _handle(p_handle)\n{\n    auto api = internal::w_msquic_api::api();\n    auto context = static_cast<context_bundle*>(api->GetContext(p_handle));\n    ++context->refcount;\n}\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_listener.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n#include \"stream/quic/datatypes/w_alpn.hpp\"\n#include \"stream/quic/events/w_listener_event.hpp\"\n#include \"stream/quic/handles/w_registration.hpp\"\n\n#include <boost/leaf.hpp>\n#include <msquic.h>\n\n#include <atomic>\n#include <span>\n#include <tuple>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief The wrapper of listener handle of msquic.\n */\nclass W_API w_listener {\n    friend internal::w_raw_access;\n\npublic:\n    using callback_type = std::function<w_status(w_listener&, w_listener_event&)>;\n\nprivate:\n    using raw_callback_type = QUIC_STATUS(HQUIC, void*, QUIC_LISTENER_EVENT*);\n\n    struct context_bundle {\n        callback_type callback;\n        std::atomic<bool> running = false;\n        std::atomic<int> refcount = 0;\n        bool closed = false; // to avoid double free in reentrancy of close() in callback.\n    };\n\n    static QUIC_STATUS internal_raw_callback(HQUIC p_listener_raw,\n                                             void* p_context_raw,\n                                             QUIC_LISTENER_EVENT* p_event_raw);\n\npublic:\n    /**\n     * @brief construct an empty handle.\n     * @note use static factory function `open` to create a valid handle.\n     */\n    w_listener() {}\n\n    w_listener(const w_listener&) = delete;\n    w_listener(w_listener&& p_other) noexcept\n        : _handle(std::exchange(p_other._handle, nullptr))\n    {}\n\n    w_listener& operator=(const w_listener&) = delete;\n    w_listener& operator=(w_listener&& p_other) noexcept\n    {\n        std::swap(_handle, p_other._handle);\n        return *this;\n    }\n\n    ~w_listener() { close(); }\n\n    /**\n     * @brief whether the handle is open/valid or not.\n     */\n    [[nodiscard]] bool is_valid() const noexcept { return _handle; }\n\n    /**\n     * @brief whether it has been started and running.\n     */\n    [[nodiscard]] bool is_running() const noexcept;\n\n    /**\n     * @brief open/create a listener.\n     * @param p_reg       registration (execution context).\n     * @param p_callback  listener callback.\n     * @return a listener instance on success.\n     */\n    [[nodiscard]] static auto open(w_registration& p_reg, callback_type p_callback) noexcept\n        -> boost::leaf::result<w_listener>;\n\n    /**\n     * @brief set callback.\n     * @param p_callback  listener callback.\n     * @return success or failure.\n     */\n    auto set_callback(callback_type p_callback) -> boost::leaf::result<void>;\n\n    /**\n     * @brief start to listen.\n     * @param p_address  address and port to listen on.\n     * @param p_alpn     application-layer protocol negotiation.\n     * @return\n     */\n    w_status start(const w_address& p_address, w_alpn_view p_alpn);\n\n    /**\n     * @brief stop the listener.\n     *\n     * This is a non-blocking call, completion will be notified\n     * by stop_complete event in callback.\n     */\n    void stop();\n\n    /**\n     * @brief close the listener handle.\n     *\n     * after this the instance will be unusable.\n     */\n    void close();\n\nprivate:\n    auto raw() noexcept { return _handle; }\n    auto raw() const noexcept { return _handle; }\n\n    explicit w_listener(internal::w_raw_tag, HQUIC p_handle) noexcept;\n\n    HQUIC _handle = nullptr;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_registration.cpp",
    "content": "#include \"stream/quic/handles/w_registration.hpp\"\n\n#include \"stream/quic/internal/w_msquic_api.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n\n#include \"wolf.hpp\"\n\nnamespace wolf::stream::quic {\n\nauto w_registration::open() noexcept -> boost::leaf::result<w_registration>\n{\n    HQUIC handle;\n    auto api = internal::w_msquic_api::api();\n\n    w_status status = api->RegistrationOpen(nullptr, &handle);\n    if (status.failed()) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         wolf::format(\"couldn't open/create registration: {}\", status_to_str(status)));\n    }\n\n    return w_registration(internal::w_raw_tag{}, handle);\n}\n\nauto w_registration::open(const w_registration_config& p_config) noexcept\n    -> boost::leaf::result<w_registration>\n{\n    HQUIC handle;\n    auto api = internal::w_msquic_api::api();\n\n    auto config_raw = internal::w_raw_access::raw(p_config);\n\n    w_status status = api->RegistrationOpen(config_raw, &handle);\n    if (status.failed()) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         wolf::format(\"couldn't open/create registration: {}\", status_to_str(status)));\n    }\n\n    return w_registration(internal::w_raw_tag{}, handle);\n}\n\nvoid w_registration::shutdown(wolf::w_flags<w_connection_shutdown_flag> p_flags,\n                              std::size_t p_error_code)\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n    auto flags = static_cast<QUIC_CONNECTION_SHUTDOWN_FLAGS>(p_flags.to_underlying());\n    api->RegistrationShutdown(_handle, flags, p_error_code);\n}\n\nvoid w_registration::close()\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n    api->RegistrationClose(_handle);\n    _handle = nullptr;\n}\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_registration.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/datatypes/common_flags.hpp\"\n#include \"stream/quic/datatypes/w_registration_config.hpp\"\n#include \"system/w_flags.hpp\"\n\n#include <boost/leaf.hpp>\n#include <msquic.h>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief Wrapper of registration handle of msquic.\n *\n * registration is the execution context of a quic application.\n * all connections, worker threads, internal allocations, etc\n * are controlled by registration.\n *\n * one likely won't need more than one registration in their application.\n *\n * @note make sure that the configuration handle has\n *       a shorter lifetime and closes before this registration,\n *       or there might be deadlock.\n */\nclass W_API w_registration {\n    friend internal::w_raw_access;\n\npublic:\n    /**\n     * @brief constructs an empty unusable handle.\n     * @note use static factory function `open` to create a valid handle.\n     */\n    w_registration() {}\n\n    w_registration(const w_registration&) = delete;\n    w_registration(w_registration&& p_other) noexcept\n        : _handle(std::exchange(p_other._handle, nullptr))\n    {}\n\n    w_registration& operator=(const w_registration&) = delete;\n    w_registration& operator=(w_registration&& p_other) noexcept\n    {\n        std::swap(_handle, p_other._handle);\n        return *this;\n    }\n\n    ~w_registration() { close(); }\n\n    /**\n     * @brief whether the handle is open/valid or not.\n     */\n    [[nodiscard]] bool is_valid() const noexcept { return _handle; }\n\n    /**\n     * @brief open/create a regisration with default registration config.\n     */\n    [[nodiscard]] static auto open() noexcept -> boost::leaf::result<w_registration>;\n\n    /**\n     * @brief open/create a registration with given registration config.\n     * @param p_config registration configuration.\n     */\n    [[nodiscard]] static auto open(const w_registration_config& p_config) noexcept\n        -> boost::leaf::result<w_registration>;\n\n    /**\n     * @brief shutdown the execution context along with its connections.\n     * @param p_flags connection shutdown flags.\n     * @param p_error_code error code to send to peers.\n     */\n    void shutdown(wolf::w_flags<w_connection_shutdown_flag> p_flags = w_connection_shutdown_flag::None,\n                  std::size_t p_error_code = 0);\n\n    /**\n     * @brief close the registration and free up its memory.\n     * @note the associated configuration handle\n     *       must be closed before closing the registration.\n     */\n    void close();\n\nprivate:\n    auto raw() noexcept { return _handle; }\n    auto raw() const noexcept { return _handle; }\n\n    explicit w_registration(internal::w_raw_tag, HQUIC p_handle) noexcept\n        : _handle(p_handle)\n    {}\n\n    HQUIC _handle = nullptr;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_stream.cpp",
    "content": "#include \"stream/quic/handles/w_stream.hpp\"\n\n#include \"stream/quic/internal/w_msquic_api.hpp\"\n#include \"stream/quic/events/w_stream_event.hpp\"\n\n#include \"wolf.hpp\"\n\nnamespace wolf::stream::quic {\n\nQUIC_STATUS w_stream::internal_raw_callback(HQUIC stream_raw,\n                                            void* context_raw,\n                                            QUIC_STREAM_EVENT* event_raw)\n{\n    if (!context_raw) {\n        return QUIC_STATUS_INTERNAL_ERROR;\n    }\n\n    auto context = static_cast<context_bundle*>(context_raw);\n\n    auto stream = w_stream(internal::w_raw_tag{}, stream_raw);\n    auto event = internal::w_raw_access::from_raw<w_stream_event>(event_raw);\n\n    w_status status = context->callback(stream, event);\n\n    // if stream is not closed.\n    if (stream.raw()) {\n        if (event_raw->Type == QUIC_STREAM_EVENT_SEND_COMPLETE) {\n            delete static_cast<QUIC_BUFFER*>(event_raw->SEND_COMPLETE.ClientContext);\n        }\n        if (event_raw->Type == QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE) {\n            context->running = false;\n            // not running anymore, thus no longer requires to be held for callback.\n            --context->refcount;\n        }\n    }\n\n    return status;\n}\n\nbool w_stream::is_running() const noexcept\n{\n    if (!_handle) {\n        return false;\n    }\n\n    auto api = internal::w_msquic_api::api();\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    return context->running;\n}\n\nauto w_stream::open(w_connection& p_conn,\n                    callback_type p_callback,\n                    wolf::w_flags<w_stream_open_flag> p_flags) noexcept\n    -> boost::leaf::result<w_stream>\n{\n    HQUIC handle = nullptr;\n\n    auto api = internal::w_msquic_api::api();\n\n    auto conn_raw = internal::w_raw_access::raw(p_conn);\n    if (!conn_raw) {\n        return W_FAILURE(std::errc::invalid_argument, \"given connection is not valid.\");\n    }\n\n    auto [context_ptr, callback_ptr] = make_context_callback_ptrs(std::move(p_callback));\n    if (!context_ptr || !callback_ptr) {\n        return W_FAILURE(std::errc::not_enough_memory, \"couldn't allocate for callback context.\");\n    }\n\n    w_status status = api->StreamOpen(\n        conn_raw,\n        static_cast<QUIC_STREAM_OPEN_FLAGS>(p_flags.to_underlying()),\n        (QUIC_STREAM_CALLBACK_HANDLER)callback_ptr,\n        (void*)context_ptr,\n        &handle\n    );\n    if (status.failed()) {\n        delete context_ptr;\n        return W_FAILURE(std::errc::operation_canceled,\n                         wolf::format(\"couldn't open/create stream: {}\", status_to_str(status)));\n    }\n\n    return w_stream(internal::w_raw_tag{}, handle);\n}\n\nauto w_stream::set_callback(callback_type p_callback) -> boost::leaf::result<void>\n{\n    if (!_handle) {\n        return W_FAILURE(std::errc::operation_canceled, \"stream is closed/destroyed.\");\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n\n    if (!context) {\n        return W_FAILURE(std::errc::operation_canceled, \"stream is in invalid state.\");\n    }\n\n    if (context->running) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"can't set callback when stream is active/running.\");\n    }\n\n    context->callback = std::move(p_callback);\n\n    return {};\n}\n\nw_status w_stream::start(wolf::w_flags<w_stream_start_flag> p_flags)\n{\n    if (!_handle) {\n        return w_status_code::InvalidState;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    if (!context) {\n        return w_status_code::InternalError;\n    }\n\n    if (context->running) {\n        return w_status_code::InvalidState;\n    }\n\n    w_status status = api->StreamStart(\n        _handle,\n        static_cast<QUIC_STREAM_START_FLAGS>(p_flags.to_underlying())\n    );\n    if (status.failed()) {\n        return status;\n    }\n\n    context->running = true;\n    // account one more for running stream to\n    // be passed into the callback.\n    ++context->refcount;\n\n    return status;\n}\n\nw_status w_stream::send(std::string_view p_str, wolf::w_flags<w_send_flag> p_flags)\n{\n    return send(std::span<uint8_t>((uint8_t*)p_str.data(), p_str.size()));\n}\n\nw_status w_stream::send(std::span<uint8_t> p_buffer, wolf::w_flags<w_send_flag> p_flags)\n{\n    if (!_handle) {\n        return w_status_code::InvalidState;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    // on successful send, the allocated buffer must be\n    // dealloacted in event handler callback by context pointer.\n    auto buf_ptr = new QUIC_BUFFER{\n        .Length = (unsigned int)p_buffer.size(),\n        .Buffer = p_buffer.data()\n    };\n\n    const auto flags = static_cast<QUIC_SEND_FLAGS>(p_flags.to_underlying());\n\n    w_status status = api->StreamSend(_handle, buf_ptr, 1, flags, buf_ptr);\n    if (status.failed()) {\n        delete buf_ptr;\n        return status;\n    }\n\n    return status;\n}\n\nvoid w_stream::shutdown(wolf::w_flags<w_stream_shutdown_flag> p_flags, size_t p_error_code)\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    if (!context || !context->running) {\n        return;\n    }\n\n    const auto flags = static_cast<QUIC_STREAM_SHUTDOWN_FLAGS>(p_flags.to_underlying());\n\n    api->StreamShutdown(_handle, flags, p_error_code);\n}\n\nvoid w_stream::close()\n{\n    if (!_handle) {\n        return;\n    }\n\n    auto api = internal::w_msquic_api::api();\n\n    auto context = static_cast<context_bundle*>(api->GetContext(_handle));\n    if (!context || context->closed) {\n        return;\n    }\n\n    if (--context->refcount > 0) {\n        return;\n    }\n\n    // making sure if callback calls close,\n    // it wouldn't result in reentrancy in msquic api.\n    context->closed = true;\n\n    api->StreamClose(_handle);\n    _handle = nullptr;\n    delete context;\n}\n\nauto w_stream::setup_new_raw_stream(HQUIC p_stream_raw, callback_type p_callback) noexcept\n    -> boost::leaf::result<w_stream>\n{\n    auto api = internal::w_msquic_api::api();\n\n    auto [context_ptr, callback_ptr] = make_context_callback_ptrs(std::move(p_callback));\n    if (!context_ptr) {\n        return W_FAILURE(std::errc::operation_canceled,\n                         \"couldn't allocate for context of stream callback.\");\n    }\n\n    api->SetCallbackHandler(\n        p_stream_raw,\n        (QUIC_STREAM_CALLBACK_HANDLER)callback_ptr,\n        context_ptr\n    );\n\n    // since it's already running, sets it as running\n    // and also adds a refcount for callback.\n    context_ptr->running = true;\n    ++context_ptr->refcount;\n\n    return w_stream(internal::w_raw_tag{}, p_stream_raw);\n}\n\nw_stream::w_stream(internal::w_raw_tag, HQUIC p_handle) noexcept\n    : _handle(p_handle)\n{\n    auto api = internal::w_msquic_api::api();\n    auto context = static_cast<context_bundle*>(api->GetContext(p_handle));\n    ++context->refcount;\n}\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/handles/w_stream.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/internal/common.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n#include \"stream/quic/handles/w_connection.hpp\"\n\n#include <boost/leaf.hpp>\n#include <msquic.h>\n\n#include <atomic>\n#include <span>\n#include <tuple>\n\nnamespace wolf::stream::quic {\n\nclass w_stream_event;\nclass w_connection_event_peer_stream_started;\n\n/**\n * @brief The wrapper of stream handle of msquic.\n */\nclass W_API w_stream {\n    friend class internal::w_raw_access;\n    friend class w_connection_event_peer_stream_started;\n\npublic:\n    using callback_type = std::function<w_status(w_stream&, w_stream_event&)>;\n\nprivate:\n    using raw_callback_type = QUIC_STATUS(HQUIC, void*, QUIC_STREAM_EVENT*);\n\n    struct context_bundle {\n        callback_type callback;\n        std::atomic<bool> running = false;\n        std::atomic<int> refcount = 0;\n        bool closed = false; // to avoid double free in reentrancy of close() in callback.\n    };\n\n    static QUIC_STATUS internal_raw_callback(HQUIC listener_raw,\n                                             void* context_raw,\n                                             QUIC_STREAM_EVENT* event_raw);\n\npublic:\n    /**\n     * @brief constructs an empty handle.\n     * @note use static factory function `open` to create a valid handle.\n     */\n    w_stream() {}\n\n    w_stream(const w_stream&) = delete;\n    w_stream(w_stream&& p_other) noexcept\n        : _handle(std::exchange(p_other._handle, nullptr))\n    {}\n\n    w_stream& operator=(const w_stream&) = delete;\n    w_stream& operator=(w_stream&& p_other) noexcept\n    {\n        std::swap(_handle, p_other._handle);\n        return *this;\n    }\n\n    ~w_stream() { close(); }\n\n    /**\n     * @brief whether the handle is open/valid or not.\n     */\n    [[nodiscard]] bool is_valid() const noexcept { return _handle; }\n\n    /**\n     * @brief whether it has been started and running.\n     */\n    [[nodiscard]] bool is_running() const noexcept;\n\n    /**\n     * @brief open/create a stream on a connection.\n     * @param p_conn      connection to open the stream on.\n     * @param p_callback  stream event handler callback.\n     * @return a connection instance on success.\n     */\n    [[nodiscard]] static auto open(w_connection& p_conn,\n                                   callback_type p_callback,\n                                   wolf::w_flags<w_stream_open_flag> p_flags = w_stream_open_flag::None) noexcept\n        -> boost::leaf::result<w_stream>;\n\n    /**\n     * @brief set callback.\n     * @param p_callback  event handler callback.\n     * @return success or failure.\n     */\n    auto set_callback(callback_type p_callback) -> boost::leaf::result<void>;\n\n    /**\n     * @brief start the stream.\n     * @param p_flags  flags to control the behavior of starting stream.\n     * @return status of success or failure.\n     */\n    w_status start(wolf::w_flags<w_stream_start_flag> p_flags = w_stream_start_flag::None);\n\n    /**\n     * @brief send one or more buffers into stream.\n     * @param p_str    string to send.\n     * @param p_flags  flags to control the behavior of send.\n     * @return a status inidicating success or failure.\n     */\n    w_status send(std::string_view p_str,\n                  wolf::w_flags<w_send_flag> p_flags = w_send_flag::None);\n\n    /**\n     * @brief send one or more buffers into stream.\n     * @param p_buffer  contiguous buffer to send.\n     * @param p_flags   flags to control the behavior of send.\n     * @return a status inidicating success or failure.\n     */\n    w_status send(std::span<std::uint8_t> p_buffer,\n                  wolf::w_flags<w_send_flag> p_flags = w_send_flag::None);\n\n    /**\n     * @brief shutdown the stream.\n     *\n     * This is a non-blocking call, completion will be notified\n     * by shutdown_complete event in callback.\n     */\n    void shutdown(wolf::w_flags<w_stream_shutdown_flag> p_flags = w_stream_shutdown_flag::Graceful,\n                  std::size_t p_error_code = 0);\n    /**\n     * @brief close the connection handle.\n     *\n     * after this the instance will be unusable.\n     */\n    void close();\n\nprivate:\n    /**\n     * @brief setup the new raw stream created by msquic.\n     * @param p_conn_raw  raw stream handle.\n     * @param p_config    configuration to associate with.\n     * @param p_callback  event handler callback.\n     * @return status of whether succeeded or not.\n     */\n    [[nodiscard]] static auto setup_new_raw_stream(HQUIC p_stream_raw, callback_type p_callback) noexcept\n        -> boost::leaf::result<w_stream>;\n\n    template <typename HandlerF>\n    [[nodiscard]] static auto make_context_callback_ptrs(HandlerF&& p_callback)\n        -> std::pair<context_bundle*, QUIC_STREAM_CALLBACK_HANDLER>\n    {\n        return {\n            new context_bundle{ .callback = std::forward<HandlerF>(p_callback) },\n            internal_raw_callback\n        };\n    }\n\n    auto raw() noexcept { return _handle; }\n    auto raw() const noexcept { return _handle; }\n\n    explicit w_stream(internal::w_raw_tag, HQUIC p_handle) noexcept;\n\n    HQUIC _handle = nullptr;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/internal/common.cpp",
    "content": "#include \"stream/quic/internal/common.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/internal/common.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include <utility>\n\nnamespace wolf::stream::quic::internal {\n\n/**\n * @brief Tag/Indicator of raw interaction constructor/method overload.\n */\nclass W_API w_raw_tag {};\n\n/**\n * @brief A type to befriended by types which want\n *        to expose their private raw access api to\n *        other types within the library.\n *\n * This type allow for sharing a common api between\n * any library type declaring it as friend to any other library type.\n *\n * This is to avoid redundant/hardcoded/forward-declared friend access pattern.\n *\n * It also limits the access to a certain private api, unlike direct friendship.\n *\n * \"Friends of friend are also friend\" :)\n */\nclass W_API w_raw_access {\npublic:\n    w_raw_access() = delete;\n\n    template <typename T, typename ...Args>\n    static auto from_raw(Args&& ...args)\n    {\n        return T(w_raw_tag{}, std::forward<Args>(args)...);\n    }\n\n    template <typename T>\n    static auto raw(T&& p_object)\n    {\n        return std::forward<T>(p_object).raw();\n    }\n};\n\n}  // namespace wolf::stream::quic::internal\n"
  },
  {
    "path": "wolf/stream/quic/internal/w_msquic_api.cpp",
    "content": "#include \"stream/quic/internal/w_msquic_api.hpp\"\n\n#include <exception>\n\nnamespace wolf::stream::quic::internal {\n\nstatic std::mutex g_msquic_api_table_mutex{};\nstatic const QUIC_API_TABLE* g_msquic_api_table_instance = nullptr;\n\nauto w_msquic_api::api() -> const QUIC_API_TABLE*\n{\n    auto lk = std::unique_lock(g_msquic_api_table_mutex);\n\n    if (!g_msquic_api_table_instance) {\n        QUIC_STATUS status;\n        if (QUIC_FAILED(status = MsQuicOpen2(&g_msquic_api_table_instance))) {\n            throw std::exception(\"error occured when initializing msquic library.\");\n        }\n    }\n\n    return g_msquic_api_table_instance;\n}\n\n}  // namespace wolf::stream::quic::internal\n"
  },
  {
    "path": "wolf/stream/quic/internal/w_msquic_api.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include <msquic.h>\n\n#include <mutex>\n\nnamespace wolf::stream::quic::internal {\n\n/**\n * @brief singleton msquic api function table provider.\n */\nclass W_API w_msquic_api {\npublic:\n    w_msquic_api() = delete;\n\n    /**\n     * @brief make a valid QUIC_API_TABLE pointer instance.\n     */\n    static auto api() -> const QUIC_API_TABLE*;\n};\n\n}  // namespace wolf::stream::quic::internal\n"
  },
  {
    "path": "wolf/stream/quic/w_quic.cpp",
    "content": "#include \"stream/quic/w_quic.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/w_quic.hpp",
    "content": "#ifndef WOLF_STREAM_QUIC\n#error \"WOLF_STREAM_QUIC feature is not enabled.\"\n#endif\n\n#pragma once\n\n#include \"system/w_flags.hpp\"\n\n#include \"stream/quic/datatypes/common_flags.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n#include \"stream/quic/datatypes/w_settings.hpp\"\n#include \"stream/quic/datatypes/w_address.hpp\"\n#include \"stream/quic/datatypes/w_credential_config.hpp\"\n#include \"stream/quic/datatypes/w_registration_config.hpp\"\n#include \"stream/quic/datatypes/w_new_connection_info.hpp\"\n#include \"stream/quic/datatypes/w_alpn.hpp\"\n\n#include \"stream/quic/events/w_connection_event.hpp\"\n#include \"stream/quic/events/w_listener_event.hpp\"\n#include \"stream/quic/events/w_stream_event.hpp\"\n\n#include \"stream/quic/handles/w_configuration.hpp\"\n#include \"stream/quic/handles/w_connection.hpp\"\n#include \"stream/quic/handles/w_listener.hpp\"\n#include \"stream/quic/handles/w_registration.hpp\"\n#include \"stream/quic/handles/w_stream.hpp\"\n\n#include \"stream/quic/w_quic_server.hpp\"\n#include \"stream/quic/w_quic_client.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/w_quic_client.cpp",
    "content": "#include \"stream/quic/w_quic.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/w_quic_client.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/datatypes/w_alpn.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n#include \"stream/quic/datatypes/w_settings.hpp\"\n#include \"stream/quic/datatypes/w_credential_config.hpp\"\n#include \"stream/quic/datatypes/w_registration_config.hpp\"\n#include \"stream/quic/handles/w_configuration.hpp\"\n#include \"stream/quic/handles/w_registration.hpp\"\n#include \"stream/quic/handles/w_connection.hpp\"\n\n#include \"wolf.hpp\"\n\n#include <string>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief client parameters/config bundle.\n */\nstruct w_quic_client_config {\n    std::string alpn = \"\";\n    quic::w_settings settings = quic::w_settings{\n        .peer_bidi_stream_count = 1,\n        .peer_unidi_stream_count = 1\n    };\n    quic::w_registration_config reg_config;\n    quic::w_credential_config cred_config = quic::w_credential_config(\n        quic::w_certificate_none(),\n        quic::w_credential_flag::Client\n    );\n};\n\n/**\n * @brief a simple quic client utility that holds\n *        and manages registration and configuration along with connection.\n */\nclass w_quic_client {\npublic:\n    w_quic_client(const w_quic_client&) = delete;\n    w_quic_client(w_quic_client&&) noexcept = default;\n\n    w_quic_client& operator=(const w_quic_client&&) noexcept = delete;\n    w_quic_client& operator=(w_quic_client&&) noexcept = default;\n\n    ~w_quic_client() { stop(); }\n\n    [[nodiscard]] auto& configuration() noexcept { return _configuration; }\n    [[nodiscard]] const auto& configuration() const noexcept { return _configuration; }\n\n    [[nodiscard]] auto& registration() noexcept { return _registration; }\n    [[nodiscard]] const auto& registration() const noexcept { return _registration; }\n\n    /**\n     * @brief make a valid quic client instance.\n     * @param p_server_config  client configuration bundle.\n     * @return an instance on success.\n     */\n    [[nodiscard]] static auto make(const w_quic_client_config& p_client_config)\n        -> boost::leaf::result<w_quic_client>\n    {\n        w_quic_client ret;\n\n        BOOST_LEAF_ASSIGN(ret._registration, quic::w_registration::open(p_client_config.reg_config));\n\n        auto cred_config = quic::w_credential_config(\n            quic::w_certificate_none(),\n            wolf::w_flags(quic::w_credential_flag::Client)\n            | quic::w_credential_flag::NoCertificationValidation\n        );\n\n        BOOST_LEAF_ASSIGN(ret._configuration, quic::w_configuration::open(\n            ret._registration,\n            p_client_config.settings,\n            quic::as_alpn_view(p_client_config.alpn),\n            cred_config\n        ));\n\n        ret._alpn = p_client_config.alpn;\n\n        return ret;\n    }\n\n    /**\n     * @brief run the client to connect on the given host and port with given callback.\n     * @return success or failure.\n     */\n    auto run(const char* p_host, std::uint16_t p_port, w_connection::callback_type p_connection_cb)\n        -> boost::leaf::result<void>\n    {\n        if (_connection.is_running()) {\n            return W_FAILURE(std::errc::operation_in_progress, \"already running.\");\n        }\n\n        BOOST_LEAF_ASSIGN(_connection, quic::w_connection::open(_registration, std::move(p_connection_cb)));\n\n        quic::w_status status = _connection.start(_configuration, p_host, p_port);\n        if (status.failed()) {\n            auto err_str = wolf::format(\"couldn't start connection: {}\", quic::status_to_str(status));\n            return W_FAILURE(std::errc::operation_canceled, std::move(err_str));\n        }\n\n        return {};\n    }\n\n    /**\n     * @brief stop the server.\n     */\n    void stop()\n    {\n        if (!_connection.is_running()) {\n            return;\n        }\n\n        _connection.shutdown();\n        _connection.close();\n    }\n\nprivate:\n    w_quic_client() {}\n\n    std::string _alpn;\n\n    w_registration _registration;\n    w_configuration _configuration;\n    w_connection _connection;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/quic/w_quic_server.cpp",
    "content": "#include \"stream/quic/w_quic_server.hpp\"\n"
  },
  {
    "path": "wolf/stream/quic/w_quic_server.hpp",
    "content": "#pragma once\n\n#include \"stream/quic/datatypes/w_alpn.hpp\"\n#include \"stream/quic/datatypes/w_status.hpp\"\n#include \"stream/quic/datatypes/w_settings.hpp\"\n#include \"stream/quic/datatypes/w_credential_config.hpp\"\n#include \"stream/quic/datatypes/w_registration_config.hpp\"\n#include \"stream/quic/handles/w_configuration.hpp\"\n#include \"stream/quic/handles/w_registration.hpp\"\n#include \"stream/quic/handles/w_listener.hpp\"\n\n#include \"wolf.hpp\"\n\n#include <string>\n\nnamespace wolf::stream::quic {\n\n/**\n * @brief server parameters/config bundle.\n */\nstruct w_quic_server_config {\n    std::string alpn = \"\";\n    w_settings settings{\n        .peer_bidi_stream_count = 1,\n        .peer_unidi_stream_count = 1\n    };\n    w_registration_config reg_config;\n    w_credential_config cred_config;\n};\n\n/**\n * @brief a simple quic server utility that holds\n *        and manages registration and configuration along with listener.\n */\nclass w_quic_server {\npublic:\n    w_quic_server(const w_quic_server&) = delete;\n    w_quic_server(w_quic_server&&) noexcept = default;\n\n    w_quic_server& operator=(const w_quic_server&&) noexcept = delete;\n    w_quic_server& operator=(w_quic_server&&) noexcept = default;\n\n    ~w_quic_server() { stop(); }\n\n    [[nodiscard]] auto& configuration() noexcept { return _configuration; }\n    [[nodiscard]] const auto& configuration() const noexcept { return _configuration; }\n\n    [[nodiscard]] auto& registration() noexcept { return _registration; }\n    [[nodiscard]] const auto& registration() const noexcept { return _registration; }\n\n    /**\n     * @brief make a valid quic server instance.\n     * @param p_server_config  server configuration bundle.\n     * @return an instance on success.\n     */\n    [[nodiscard]] static auto make(const w_quic_server_config& p_server_config)\n        -> boost::leaf::result<w_quic_server>\n    {\n        auto ret = w_quic_server();\n\n        BOOST_LEAF_ASSIGN(ret._registration, w_registration::open(p_server_config.reg_config));\n\n        BOOST_LEAF_ASSIGN(ret._configuration, w_configuration::open(\n            ret._registration,\n            p_server_config.settings,\n            as_alpn_view(p_server_config.alpn),\n            p_server_config.cred_config\n        ));\n\n        ret._alpn = p_server_config.alpn;\n\n        return ret;\n    }\n\n    /**\n     * @brief run the server to listen on the given port with given callback.\n     * @return success or failure.\n     */\n    auto run(std::uint16_t p_port, w_listener::callback_type p_listener_cb)\n        -> boost::leaf::result<void>\n    {\n        if (_listener.is_valid()) {\n            stop();\n        }\n\n        BOOST_LEAF_ASSIGN(_listener, w_listener::open(_registration, std::move(p_listener_cb)));\n\n        auto address = w_address(w_address_family::Unspecified, p_port);\n\n        auto status = _listener.start(address, as_alpn_view(_alpn));\n        if (status.failed()) {\n            return W_FAILURE(std::errc::operation_canceled,\n                             wolf::format(\"listener didn't start: {}\", status_to_str(status)));\n        }\n\n        return {};\n    }\n\n    /**\n     * @brief stop the server.\n     */\n    void stop()\n    {\n        if (!_listener.is_valid()) {\n            return;\n        }\n\n        _listener.stop();\n        _listener.close();\n    }\n\nprivate:\n    w_quic_server() {}\n\n    std::string _alpn;\n\n    w_registration _registration;\n    w_configuration _configuration;\n    w_listener _listener;\n};\n\n}  // namespace wolf::stream::quic\n"
  },
  {
    "path": "wolf/stream/rist/w_rist.cpp",
    "content": "#ifdef WOLF_STREAM_RIST\n\n#include \"w_rist.hpp\"\n\n#ifndef __clang__\n#include <Objbase.h>\n#endif\n\nusing w_rist = wolf::stream::rist::w_rist;\nusing w_rist_data_block = wolf::stream::rist::w_rist_data_block;\n\n#pragma region callbacks\n\nstatic int s_on_log_callback(_In_ void *p_arg, _In_ rist_log_level p_log_level,\n                             _In_z_ const char *p_msg) {\n  const gsl::not_null<w_rist *> _rist_nn(gsl::narrow_cast<w_rist *>(p_arg));\n  if (_rist_nn->on_log_callback) {\n    _rist_nn->on_log_callback(p_log_level, p_msg);\n  }\n  return S_OK;\n}\n\nstatic int s_on_auth_handler_connect_callback(_In_ void *p_arg, _In_z_ const char *p_conn_ip,\n                                              _In_ uint16_t p_conn_port,\n                                              _In_z_ const char *p_local_ip,\n                                              _In_ uint16_t p_local_port, _In_ rist_peer *p_peer) {\n  const auto _rist_nn = gsl::not_null<w_rist *>(gsl::narrow_cast<w_rist *>(p_arg));\n\n  if (_rist_nn->on_auth_connected_callback) {\n    _rist_nn->on_auth_connected_callback(p_conn_ip, p_conn_port, p_local_ip, p_local_port);\n  }\n\n  return S_OK;\n}\n\nstatic int s_on_auth_handler_disconnect_callback(_In_ void *p_arg,\n                                                 _In_ rist_peer *p_peer) {\n  const auto _rist_nn =\n      gsl::not_null<w_rist *>(gsl::narrow_cast<w_rist *>(p_arg));\n  if (_rist_nn->on_auth_disconnected_callback) {\n    _rist_nn->on_auth_disconnected_callback();\n  }\n  return S_OK;\n}\n\nstatic int s_on_receiver_data_callback(_In_ void *p_arg,\n                                       _In_ rist_data_block *p_data_block) {\n  const auto _rist_nn =\n      gsl::not_null<w_rist *>(gsl::narrow_cast<w_rist *>(p_arg));\n  const auto _data_block_nn = gsl::not_null<rist_data_block *>(p_data_block);\n\n  if (_rist_nn->on_receiver_data_callback) {\n    auto _block = w_rist_data_block(std::move(*p_data_block));\n    _rist_nn->on_receiver_data_callback(_block);\n  } else {\n    // release block\n    rist_receiver_data_block_free2(&p_data_block);\n  }\n  return S_OK;\n}\n\n#pragma endregion\n\nw_rist::w_rist(_In_ rist_ctx_mode p_mode, _In_ rist_profile p_profile,\n               _In_ uint16_t p_loss_percentage,\n               _In_ rist_log_level p_log_level) noexcept\n    : _mode(p_mode), _profile(p_profile), _loss_percentage(p_loss_percentage),\n      _log_level(p_log_level), _log(nullptr), _ctx(nullptr), _peer(nullptr) {}\n \n w_rist::~w_rist() noexcept {\n  if (this->_ctx != nullptr) {\n    if (this->_peer != nullptr) {\n      std::ignore = rist_peer_destroy(this->_ctx, this->_peer);\n      this->_peer = nullptr;\n    }\n    std::ignore = rist_destroy(this->_ctx);\n    this->_ctx = nullptr;\n  }\n  _release_log();\n}\n\n void w_rist::_release_log() {\n  if (this->_log == nullptr)\n    return;\n\n  rist_logging_unset_global();\n  rist_logging_settings_free2(&this->_log);\n}\n\nboost::leaf::result<int> w_rist::init() {\n\n  // first release resources of context and log\n  _release_log();\n  if (this->_ctx != nullptr) {\n    std::ignore = rist_destroy(this->_ctx);\n  }\n\n  // now create a log\n  if (rist_logging_set(&this->_log, this->_log_level, s_on_log_callback, this,\n                       nullptr, stderr) != 0) {\n    return W_FAILURE(std::errc::operation_canceled,\n                 \"could not create a rist log callback\");\n  }\n\n  // create a rist context\n  constexpr uint16_t _max_loss = 22;\n  if (this->_mode == rist_ctx_mode::RIST_SENDER_MODE) {\n\n    // create a sender\n    const auto _ret =\n        rist_sender_create(&this->_ctx, this->_profile, 0, this->_log);\n    if (_ret != 0) {\n      return W_FAILURE(std::errc::operation_canceled,\n                   \"could not create a rist sender context\");\n    }\n\n    if (this->_loss_percentage > 0) {\n      this->_ctx->sender_ctx->simulate_loss = true;\n      this->_ctx->sender_ctx->loss_percentage =\n          this->_loss_percentage > _max_loss ? _max_loss\n                                             : this->_loss_percentage;\n    }\n  } else {\n    // create a receiver\n    const auto _ret =\n        rist_receiver_create(&this->_ctx, this->_profile, this->_log);\n\n    if (_ret != 0) {\n      return W_FAILURE(std::errc::operation_canceled,\n                   \"could not create a rist receiver context\");\n    }\n\n    if (this->_loss_percentage > 0) {\n      this->_ctx->receiver_ctx->simulate_loss = true;\n      this->_ctx->receiver_ctx->loss_percentage =\n          this->_loss_percentage > _max_loss ? _max_loss\n                                             : this->_loss_percentage;\n    }\n\n    if (rist_receiver_data_callback_set2(\n            this->_ctx, s_on_receiver_data_callback, this) != 0) {\n      return W_FAILURE(std::errc::operation_canceled,\n                   \"could not set data receiver callback\");\n    }\n  }\n\n  if (rist_auth_handler_set(this->_ctx, s_on_auth_handler_connect_callback,\n                            s_on_auth_handler_disconnect_callback, this) != 0) {\n    return W_FAILURE(std::errc::operation_canceled,\n                 \"could not set rist auth handler\");\n  }\n\n  return S_OK;\n}\n\nboost::leaf::result<int>\nw_rist::connect(_In_ const std::string_view p_endpoint) {\n\n  if (p_endpoint.empty()) {\n    return W_FAILURE(std::errc::bad_address, \"missing endpoint url\");\n  }\n\n  if (this->_peer != nullptr) {\n    std::ignore = rist_peer_destroy(this->_ctx, this->_peer);\n  }\n\n  // rely on the library to parse the url\n  auto *_peer_config =\n      gsl::owner<rist_peer_config *>(calloc(1, sizeof(rist_peer_config)));\n  // check for memory violation\n  std::ignore = gsl::not_null<rist_peer_config *>(_peer_config);\n\n\n  rist_peer_config_defaults_set(_peer_config);\n  //if (parse_url_options(url_local, _peer_config) != 0) {\n  //  return W_FAILURE(std::errc::bad_address,\n  //               \"could not parse peer options for receiver\");\n  //}\n\n  if (rist_parse_address2(p_endpoint.data(), &_peer_config) != 0) {\n    return W_FAILURE(std::errc::bad_address,\n                 \"could not parse peer options for receiver\");\n  }\n\n  if (rist_peer_create(this->_ctx, &this->_peer, _peer_config) != 0) {\n    return W_FAILURE(std::errc::operation_canceled,\n                 \"could not add peer connector to receiver\");\n  }\n\n  free(_peer_config);\n\n  if (rist_start(this->_ctx) != 0) {\n    return W_FAILURE(std::errc::operation_canceled,\n                 \"could not add peer connector to receiver\");\n  }\n\n  return S_OK;\n}\n\nboost::leaf::result<size_t>\nw_rist::send(_In_ const w_rist_data_block &p_block) {\n  auto _bytes = rist_sender_data_write(this->_ctx, p_block._block);\n  return _bytes >= 0\n             ? boost::leaf::result<size_t>(gsl::narrow_cast<size_t>(_bytes))\n             : W_FAILURE(std::errc::no_message,\n                         \"could not send data block to the rist stream\");\n}\n\n//boost::leaf::result<size_t> w_rist::receive(_Inout_ w_rist_data_block &p_block,\n//                                            _In_ int p_timeout_ms) {\n//  const gsl::not_null<rist_ctx *> _ctx_nn(this->_ctx);\n//  auto _bytes =\n//      rist_receiver_data_read2(_ctx_nn, &p_block._block, p_timeout_ms);\n//  return _bytes >= 0\n//             ? boost::leaf::result<size_t>(gsl::narrow_cast<size_t>(_bytes))\n//             : W_FAILURE(std::errc::no_message,\n//                     \"could not read data block from the rist stream\");\n//  return S_OK;\n//}\n\n#endif"
  },
  {
    "path": "wolf/stream/rist/w_rist.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright � 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_STREAM_RIST\n\n#pragma once\n\n#include \"w_rist_data_block.hpp\"\n#include <wolf/wolf.hpp>\n\nnamespace wolf::stream::rist {\nclass w_rist {\npublic:\n  /*\n   * constructor of the rist stream\n   * @param p_mode, the context mode\n   * @param p_profile, the rist profile\n   * @param p_loss_percentage, the loss percentage of rist stream\n   * @param p_log_level, the log level\n   */\n  W_API w_rist(_In_ rist_ctx_mode p_mode, _In_ rist_profile p_profile,\n               _In_ uint16_t p_loss_percentage,\n               _In_ rist_log_level p_log_level) noexcept;\n\n  // move constructor.\n  W_API w_rist(w_rist &&p_other) noexcept = default;\n  // move assignment operator.\n  W_API w_rist &operator=(w_rist &&p_other) noexcept = default;\n\n  // destructor\n  W_API virtual ~w_rist();\n\n  /*\n   * initialize ris stream\n   * @returns result\n   */\n  W_API boost::leaf::result<int> init();\n\n  /**\n   * connect or bind to the url\n   * @param p_endpoint, the destination endpoint of rist stream\n   */\n  W_API\n  boost::leaf::result<int> connect(_In_ std::string_view p_endpoint);\n\n  /**\n   * write a data block to the rist stream\n   * @param p_block, the data block\n   * @returns the number of written bytes with result\n   */\n  W_API boost::leaf::result<size_t> send(_In_ const w_rist_data_block &p_block);\n\n  ///**\n  // * set data to rist data block\n  // * @param p_block, the data block\n  // * @param p_timeout, read timeout in milliseconds\n  // * @returns the number of read bytes with result\n  // */\n  // W_API boost::leaf::result<size_t> receive(_Inout_ w_rist_data_block\n  // &p_block,\n  //                                          _In_ int p_timeout_ms);\n\n  // this callback will be called on log\n  std::function<void(_In_ rist_log_level /*p_log_level*/,\n                     _In_ std::string_view /*p_msg*/)>\n      on_log_callback;\n\n  // this signal will be called on auth connection\n  std::function<void(\n      _In_z_ std::string_view /*p_conn_ip*/, _In_ uint16_t /*p_conn_port*/,\n      _In_z_ std::string_view /*p_local_ip*/, _In_ uint16_t /*p_local_port*/)>\n      on_auth_connected_callback;\n\n  // this signal will be called after disconnect\n  std::function<void()> on_auth_disconnected_callback;\n\n  // this signal will be called on receiving data\n  std::function<void(_In_ const w_rist_data_block &)> on_receiver_data_callback;\n\nprivate:\n  w_rist(const w_rist &) = delete;\n  w_rist &operator=(const w_rist &) = delete;\n  void _release_log();\n\n  rist_ctx_mode _mode = rist_ctx_mode::RIST_SENDER_MODE;\n  rist_profile _profile = rist_profile::RIST_PROFILE_MAIN;\n  uint16_t _loss_percentage = 0;\n  rist_log_level _log_level = rist_log_level::RIST_LOG_DEBUG;\n  rist_logging_settings *_log = nullptr;\n  rist_ctx *_ctx = nullptr;\n  rist_peer *_peer = nullptr;\n};\n} // namespace wolf::stream::rist\n\n#endif // WOLF_STREAM_RIST\n"
  },
  {
    "path": "wolf/stream/rist/w_rist_data_block.cpp",
    "content": "#ifdef WOLF_STREAM_RIST\n\n#include \"w_rist_data_block.hpp\"\n\nusing w_rist_data_block = wolf::stream::rist::w_rist_data_block;\n\nw_rist_data_block::w_rist_data_block() noexcept {\n  this->_block = new (std::nothrow) rist_data_block();\n  // check for memory access violation\n  std::ignore = gsl::not_null<rist_data_block *>(this->_block);\n}\n\n  // move constructor.\nw_rist_data_block::w_rist_data_block(rist_data_block &&p_other) noexcept {\n  if (this->_block != nullptr) {\n    rist_receiver_data_block_free2(&this->_block);\n  }\n  this->_block = std::move(&p_other);\n}\n\nw_rist_data_block::~w_rist_data_block() {\n  if (this->_block == nullptr)\n    return;\n  rist_receiver_data_block_free2(&this->_block);\n  delete this->_block;\n  this->_block = nullptr;\n}\n\nvoid w_rist_data_block::set(\n    _In_ const std::tuple<const void *, size_t> &p_data) noexcept {\n  this->_block->ts_ntp = 0; \n  this->_block->payload = std::get<0>(p_data);\n  this->_block->payload_len = std::get<1>(p_data);\n}\n\nstd::tuple<const void *, size_t> w_rist_data_block::get() const {\n  return std::make_tuple(this->_block->payload, this->_block->payload_len);\n}\n\nconst void* w_rist_data_block::get_data() const {\n  return this->_block->payload;\n}\n\nsize_t w_rist_data_block::get_data_len() const {\n  return this->_block->payload_len;\n}\n\nstd::string w_rist_data_block::to_string() const {\n  return std::string(gsl::narrow_cast<const char *>(this->_block->payload),\n                     this->_block->payload_len);\n}\n\n#endif"
  },
  {
    "path": "wolf/stream/rist/w_rist_data_block.hpp",
    "content": "﻿/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_STREAM_RIST\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#include <DISABLE_ANALYSIS_END>\n#include <librist/librist.h>\n#include <rist-private.h>\n\nnamespace wolf::stream::rist {\nclass w_rist_data_block {\n  friend class w_rist;\n\npublic:\n  W_API w_rist_data_block() noexcept;\n  W_API virtual ~w_rist_data_block();\n\n  // move constructor\n  W_API w_rist_data_block(w_rist_data_block &&p_other) noexcept = default;\n  // move rist_data_block\n  W_API explicit w_rist_data_block(rist_data_block &&p_other) noexcept;\n\n  // move assignment operator\n  W_API w_rist_data_block &\n  operator=(w_rist_data_block &&p_other) noexcept = default;\n\n  /**\n   * set data to rist data block\n   * @param p_data, data and size of rist\n   * @returns result\n   */\n  W_API void set(_In_ const std::tuple<const void *, size_t> &p_data) noexcept;\n\n  /**\n   * get a tuple contains data and len of data\n   * @returns result of data with size\n   */\n  W_API std::tuple<const void *, size_t> get() const;\n\n  /**\n   * get data of rist data block\n   * @returns pointer to the data\n   */\n  W_API\n  const void *get_data() const;\n\n  /**\n   * get data len of rist data block\n   * @returns size of data\n   */\n  W_API\n  size_t get_data_len() const;\n\n  /**\n   * get data block as string\n   * @returns result of data with size\n   */\n  std::string to_string() const;\n\nprivate:\n  // copy constructor\n  w_rist_data_block(const w_rist_data_block &) = delete;\n  // copy operator\n  w_rist_data_block &operator=(const w_rist_data_block &) = delete;\n\n  rist_data_block *_block = nullptr;\n};\n} // namespace wolf::stream::rist\n\n#endif // WOLF_STREAM_RIST"
  },
  {
    "path": "wolf/stream/test/ffmpeg_stream.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_MEDIA_FFMPEG)\n\n#pragma once\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf.hpp>\n\n#include <media/ffmpeg/w_ffmpeg.hpp>\n#include <media/w_openal.hpp>\n\nBOOST_AUTO_TEST_CASE(ffmpeg_stream_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"ffmpeg_stream_test is running\" << std::endl;\n\n  using w_av_set_opt = wolf::media::ffmpeg::w_av_set_opt;\n  const auto _opt = std::vector<w_av_set_opt>();\n\n  constexpr auto _url = \"srt://127.0.0.1:554?mode=caller&transtype=live&timeout=5000000\";\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        using namespace std::chrono_literals;\n        using w_av_packet = wolf::media::ffmpeg::w_av_packet;\n        using w_ffmpeg = wolf::media::ffmpeg::w_ffmpeg;\n        using w_av_config = wolf::media::ffmpeg::w_av_config;\n        using w_av_codec_opt = wolf::media::ffmpeg::w_av_codec_opt;\n        using w_av_frame = wolf::media::ffmpeg::w_av_frame;\n        using w_openal = wolf::media::w_openal;\n\n        // frame index\n        int _index = 0;\n        // 5 seconds for io socket timeout\n        const auto t0 = std::chrono::high_resolution_clock::now();\n        bool _video_initialized = false;\n        bool _audio_initialized = false;\n        wolf::media::ffmpeg::w_decoder _video_decoder = {};\n        wolf::media::ffmpeg::w_decoder _audio_decoder = {};\n        wolf::media::ffmpeg::w_av_config _audio_config = {};\n        wolf::media::w_openal_config _openal_config = {};\n        wolf::media::w_openal _openal = {};\n        std::unique_ptr<w_av_frame> _av_video_frame;\n        std::unique_ptr<w_av_frame> _av_audio_frame;\n        auto _width = 0;\n        auto _height = 0;\n\n        auto _on_frame_cb =\n            [&](const w_av_packet &p_packet, const AVStream *p_audio_stream,\n                           const AVStream *p_video_stream) -> bool {\n          const auto _stream_index = p_packet.get_stream_index();\n          if (p_video_stream) {\n            std::cout << \"got video frame\" << std::endl;\n\n            if (_video_initialized == false) {\n              auto _codec_param = p_video_stream->codecpar;\n              _width = _codec_param->width;\n              _height = _codec_param->height;\n\n              const auto _codec_id = _codec_param->codec_id;\n              const auto _fmt = gsl::narrow_cast<AVPixelFormat>(_codec_param->format);\n\n              const auto _config = w_av_config(_fmt, _width, _height);\n\n              const auto _codec_opt = w_av_codec_opt{\n                  _codec_param->bit_rate, /*bitrate*/\n                  60,                     /*fps*/\n                  600,                    /*gop*/\n                  _codec_param->level,    /*level*/\n                  2,                      /*max_b_frames*/\n                  3,                      /*refs*/\n                  -1,                     /*thread_count*/\n              };\n\n              auto _decoder_res = w_ffmpeg::create_decoder(_config, _codec_id, _codec_opt);\n              if (_decoder_res.has_error()) {\n                return false;  // close it\n              }\n\n              _video_decoder = std::move(_decoder_res.value());\n\n              // create destination avframe for decoder\n              _av_video_frame =\n                  std::make_unique<w_av_frame>((w_av_config &&) std::move(_config));\n\n              auto _decoded_frame_res = _av_video_frame->init();\n              if (_decoded_frame_res.has_error()) {\n                std::cout << \"could not initialize decoder\" << std::endl;\n                return false;  // close it\n              }\n\n              _video_initialized = true;\n            }\n\n            auto _res = _video_decoder.decode(p_packet, *_av_video_frame);\n            if (_res.has_error()) {\n              std::cout << \"could not decode\" << std::endl;\n            } else {\n              auto _dst_config = w_av_config(AVPixelFormat::AV_PIX_FMT_RGBA, _width, _height);\n\n              auto _rgba_frame =\n                  _av_video_frame->convert_video((w_av_config&&)std::move(_dst_config));\n              if (_rgba_frame.has_error()) {\n                std::cout << \"could not convert av video frame to rgb frame\" << std::endl;\n              } else {\n                const auto _path = std::filesystem::current_path().append(\n                    \"/\" + std::to_string(_index++) + \"_rist_decoded.png\");\n                //_rgba_frame.value().save_video_frame_to_img_file(_path);\n                std::cout << \"rgb frame created\" << std::endl;\n              }\n            }\n          } else if (p_audio_stream) {\n            std::cout << \"got audio frame\" << std::endl;\n\n            if (_audio_initialized == false) {\n              auto _codec_param = p_audio_stream->codecpar;\n\n              const auto _codec_id = _codec_param->codec_id;\n              _audio_config.nb_channels = _codec_param->channels;\n              _audio_config.sample_rate = _codec_param->sample_rate;\n\n              const auto _codec_opt = w_av_codec_opt{};\n\n              auto _decoder_res = w_ffmpeg::create_decoder(_audio_config, _codec_id, _codec_opt);\n              if (_decoder_res.has_error()) {\n                return false;  // close it\n              }\n\n              _audio_config.sample_fmts =\n                  gsl::narrow_cast<AVSampleFormat>(*_decoder_res->ctx.codec->sample_fmts);\n              _audio_decoder = std::move(_decoder_res.value());\n\n              _openal_config = {AL_FORMAT_STEREO16, _audio_config.sample_rate, 25,\n                                _audio_config.nb_channels};\n\n              // create destination avframe for decoder\n              _av_audio_frame =\n                  std::make_unique<w_av_frame>((w_av_config &&) std::move(_audio_config));\n\n              auto _decoded_frame_res = _av_audio_frame->init();\n              if (_decoded_frame_res.has_error()) {\n                std::cout << \"could not initialize decoder\" << std::endl;\n                return false;  // close it\n              }\n\n              auto _ret = _openal.init(_openal_config);\n\n              if (_ret.has_error()) {\n                std::cout << \"could not initialize openal\" << std::endl;\n                return false;  // close it\n              }\n\n              _audio_initialized = true;\n            }\n\n            auto _res = _audio_decoder.decode(p_packet, *_av_audio_frame);\n            if (_res.has_error()) {\n              std::cout << \"could not decode\" << std::endl;\n            } else {\n              auto _frame = _av_audio_frame->get();\n              std::cout << \"audio size: \" << std::get<1>(_frame) << std::endl;\n\n              auto _dst_config = _audio_config;\n\n              auto _audio_frame = _av_audio_frame->convert_audio(\n                  gsl::narrow_cast<w_av_config &&>(std::move(_dst_config)));\n              if (_audio_frame.has_error()) {\n                std::cout << \"could not convert av audio frame\" << std::endl;\n              } else {\n                std::cout << \"audio frame created\" << std::endl;\n\n                auto _content = _audio_frame.value().get();\n                auto _data = std::get<0>(_content);\n                auto _size = std::get<1>(_content);\n\n                if (_data && *_data && _size) {\n                  const auto _ret =\n                      _openal.update(gsl::narrow_cast<const uint8_t *>(*_data), _size);\n                  if (_ret.has_error()) {\n                    std::cout << \"could not update openal because \" << std::endl;\n                  }\n                }\n              }\n            }\n          }\n          const auto t1 = std::chrono::high_resolution_clock::now();\n          if (std::chrono::duration_cast<std::chrono::seconds>(t1 - t0) > 20s) {\n            return false;\n          }\n          return true;\n        };\n\n        BOOST_CHECK(w_ffmpeg::open_stream(_url, _opt, _on_frame_cb));\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        std::cout << \"got error :\" << p_trace << std::endl;\n        BOOST_REQUIRE(false);\n      },\n      [] {\n        std::cout << \"got an error!\" << std::endl;\n        BOOST_ERROR(false);\n      });\n\n  std::cout << \"ffmpeg_stream_test is done\" << std::endl;\n}\n\n#endif"
  },
  {
    "path": "wolf/stream/test/grpc.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_STREAM_GRPC)\n\n#pragma once\n\n#include <wolf.hpp>\n#include <system/w_leak_detector.hpp>\n#include <boost/test/included/unit_test.hpp>\n\n#include <stream/grpc/w_grpc_client.hpp>\n\n#include <raft.grpc.pb.h>\n\nusing w_grpc_client = wolf::stream::rpc::w_grpc_client;\n\nBOOST_AUTO_TEST_CASE(grpc_client_unary_test) {\n  // const wolf::system::w_leak_detector _detector = {};\n  constexpr auto _test_name = \"'grpc_client_unary_test'\";\n  std::cout << \"entering test case \" << _test_name << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        // create a client\n        w_grpc_client _client{};\n        BOOST_LEAF_CHECK(_client.init(\"localhost\", gsl::narrow_cast<short>(50051)));\n\n        const auto _msg_id = std::string(\"unary\");\n\n        wolf::raft::RaftBootstrapReq _req{};\n        _req.set_msg_id(_msg_id);\n        _req.set_number_of_nodes(7);\n\n        wolf::raft::RaftBootstrapRes _res{};\n\n        auto send_grpc_fn =\n            [&](_In_ wolf::raft::RaftBootstrapReq request,\n                _Inout_ wolf::raft::RaftBootstrapRes response) -> boost::asio::awaitable<void> {\n          return _client\n              .send_unary<&wolf::raft::Raft::Stub::PrepareAsyncBootstrap, wolf::raft::Raft::Stub,\n                          wolf::raft::RaftBootstrapReq, wolf::raft::RaftBootstrapRes>(request,\n                                                                                      response);\n        };\n\n        auto timeout = std::chrono::seconds(3);\n        _client.exec(std::move(timeout), send_grpc_fn, _req, _res);\n\n        std::cout << \"grpc client sent unary request. msg_id: \" << _req.msg_id()\n                  << \" number_of_nodes: \" << _req.number_of_nodes() << std::endl;\n        return {};\n      },\n      [](const w_trace& p_trace) {\n        const auto _msg =\n            wolf::format(\"grpc_client_unary_test got an error: {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] { BOOST_ERROR(\"grpc_client_unary_test got an error!\"); });\n\n  std::cout << \"leaving test case \" << _test_name << std::endl;\n}\n\n//BOOST_AUTO_TEST_CASE(grpc_client_stream_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  const std::string url = \"localhost\";\n//\n//  std::unique_ptr<w_grpc_client> client = std::make_unique<w_grpc_client>();\n//\n//  boost::leaf::try_handle_all(\n//      [&]() -> boost::leaf::result<void> {\n//        auto send_grpc =\n//            [&](_In_ wolf::raft::RaftBootstrapReq& request,\n//                _Inout_ wolf::raft::RaftBootstrapRes& response) -> boost::asio::awaitable<void> {\n//          return client->send_stream<&wolf::raft::Raft::Stub::PrepareAsyncBootstrapClientStreaming,\n//                                           wolf::raft::Raft::Stub, wolf::raft::RaftBootstrapReq,\n//                                           wolf::raft::RaftBootstrapRes>(request, response);\n//        };\n//\n//        client->init(url, 50051);\n//\n//        wolf::raft::RaftBootstrapReq request;\n//        request.set_msg_id(\"client streaming\");\n//        request.set_number_of_nodes(6);\n//        wolf::raft::RaftBootstrapRes response;\n//\n//        auto timeout = std::chrono::seconds(3);\n//        client->run(std::move(timeout), send_grpc, request, response);\n//\n//        std::cout << \"grpc client sent streaming request. msg_id: \" << request.msg_id()\n//                  << \" number_of_nodes: \" << request.number_of_nodes() << std::endl;\n//        return {};\n//      },\n//      [](const w_trace& p_trace) {\n//        const auto _msg = wolf::format(\"grpc_client_stream_test got an error: {}\", p_trace.to_string());\n//        BOOST_ERROR(_msg);\n//      },\n//      [] { BOOST_ERROR(\"grpc_client_stream_test got an error!\"); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(grpc_client_bidirectional_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  const std::string url = \"localhost\";\n//  std::unique_ptr<w_grpc_client> client = std::make_unique<w_grpc_client>();\n//\n//  boost::leaf::try_handle_all(\n//      [&]() -> boost::leaf::result<void> {\n//        client->init(url, 50051);\n//        wolf::raft::RaftBootstrapReq request;\n//        request.set_msg_id(\"client bidirectional\");\n//        request.set_number_of_nodes(7);\n//        wolf::raft::RaftBootstrapRes response;\n//\n//        auto send_grpc =\n//            [&](_In_ wolf::raft::RaftBootstrapReq& request,\n//                _Inout_ wolf::raft::RaftBootstrapRes& response) -> boost::asio::awaitable<void> {\n//          return client->send_bidirectional<\n//              &wolf::raft::Raft::Stub::PrepareAsyncBootstrapBidirectionalStreaming,\n//              wolf::raft::Raft::Stub, wolf::raft::RaftBootstrapReq, wolf::raft::RaftBootstrapRes>(\n//              request, response);\n//        };\n//\n//        auto timeout = std::chrono::seconds(3);\n//        client->run(std::move(timeout), send_grpc, request, response);\n//        std::cout << \"grpc client sent bidirectional request. msg_id: \" << request.msg_id()\n//                  << \" number_of_nodes: \" << request.number_of_nodes() << std::endl;\n//        return {};\n//      },\n//      [](const w_trace& p_trace) {\n//        const auto _msg =\n//            wolf::format(\"grpc_client_bidirectional_test got an error: {}\", p_trace.to_string());\n//        BOOST_ERROR(_msg);\n//      },\n//      [] { BOOST_ERROR(\"grpc_client_bidirectional_test got an error!\"); });\n//}\n\n#endif"
  },
  {
    "path": "wolf/stream/test/quic.hpp",
    "content": "#if defined(WOLF_TEST) && defined(WOLF_STREAM_QUIC)\n\n#pragma once\n\n#include <wolf.hpp>\n#include <system/w_leak_detector.hpp>\n#include <boost/test/included/unit_test.hpp>\n\n#include <stream/quic/w_quic.hpp>\n\nnamespace quic = wolf::stream::quic;\n\nBOOST_AUTO_TEST_CASE(msquic_base_types) {\n    BOOST_REQUIRE(quic::w_status(quic::w_status_code::Success).succeeded());\n    BOOST_REQUIRE(quic::w_status(quic::w_status_code::Aborted).failed());\n\n    {\n        auto status_code = quic::w_status_code::Success;\n        auto status = quic::w_status(status_code);\n        BOOST_REQUIRE(quic::status_to_str(status_code) == quic::status_to_str(status));\n    }\n}\n\nBOOST_AUTO_TEST_CASE(msquic_server_client) {\n    boost::leaf::try_handle_all(\n        []() -> boost::leaf::result<void> {\n            std::uint8_t cert_hash[20] = {\n                // 5C39C7B31216288A00F74CC11DB5E9D7B3AA421D\n                0x5C, 0x39, 0xC7, 0xB3,\n                0x12, 0x16, 0x28, 0x8A,\n                0x00, 0xF7, 0x4C, 0xC1,\n                0x1D, 0xB5, 0xE9, 0xD7,\n                0xB3, 0xAA, 0x42, 0x1D\n            };\n            auto cert = quic::w_certificate_hash(cert_hash);\n            auto cred_conf = quic::w_credential_config(cert);\n\n            BOOST_LEAF_AUTO(server, quic::w_quic_server::make(quic::w_quic_server_config{\n                .alpn = \"sample\",\n                .settings = quic::w_settings{\n                    .idle_timeout_ms = 2000,\n                    .peer_bidi_stream_count = 1,\n                    .peer_unidi_stream_count = 1\n                },\n                .reg_config = quic::w_registration_config(\"server\"),\n                .cred_config = std::move(cred_conf)\n            }));\n\n            bool server_received = false;\n\n            auto server_stream_cb = [&](quic::w_stream& p_stream,\n                                        quic::w_stream_event& p_event) -> quic::w_status {\n                std::cout << \" [quic-server] stream callback: event: \" << p_event.name() << std::endl;\n                return p_event.visit(wolf::w_overloaded{\n                    [&](const quic::w_stream_event_start_complete&) {\n                        auto status = p_stream.send(\"Hello Client!\");\n                        BOOST_REQUIRE(status.succeeded());\n                        return quic::w_status_code::Success;\n                    },\n                    [&](const quic::w_stream_event_receive& p_ev) {\n                        BOOST_CHECK(p_ev.buffers().size() == 1);\n                        for (auto&& buffer : p_ev.buffers()) {\n                            auto str = std::string_view((const char*)buffer.data(), buffer.size());\n                            std::cout << \" [quic-server] stream: received: \" << str << std::endl;\n                            BOOST_CHECK(str == \"Hello Server!\");\n                        }\n                        server_received = true;\n                        return quic::w_status_code::Success;\n                    },\n                    [](const auto&) { return quic::w_status_code::Success; }\n                });\n            };\n\n            auto server_connection_cb = [&](quic::w_connection& p_conn,\n                                            quic::w_connection_event& p_event) -> quic::w_status {\n                std::cout << \" [quic-server] connection callback: event: \" << p_event.name() << std::endl;\n                return p_event.visit(wolf::w_overloaded{\n                    [&](const quic::w_connection_event_peer_stream_started& p_ev) {\n                        if (p_ev.is_bidirectional()) {\n                            auto stream = p_ev.accept_stream(server_stream_cb);\n                            BOOST_REQUIRE(stream);\n                            auto status = stream->send(\"Hello Client!\");\n                            BOOST_REQUIRE(status.succeeded());\n                        } else {\n                            p_ev.accept_stream(server_stream_cb);\n                            auto sender_stream = quic::w_stream::open(p_conn,\n                                                    server_stream_cb,\n                                                    quic::w_stream_open_flag::Unidirectional);\n                            BOOST_REQUIRE(sender_stream);\n                            auto status = sender_stream->start();\n                            BOOST_REQUIRE(status.succeeded());\n                        }\n                        return quic::w_status_code::Success;\n                    },\n                    [&](const auto&) { return quic::w_status_code::Success; }\n                });\n            };\n\n            auto server_listener_cb = [&](quic::w_listener& p_listener,\n                                          quic::w_listener_event& p_event) -> quic::w_status {\n                std::cout << \" [quic-server] listener callback: event: \" << p_event.name() << std::endl;\n                return p_event.visit(wolf::w_overloaded{\n                    [&](quic::w_listener_event_new_connection&& p_ev) -> quic::w_status {\n                        auto res = p_ev.accept_connection(server.configuration(), server_connection_cb);\n                        BOOST_REQUIRE(res);\n                        return res ? quic::w_status_code::Success\n                                   : quic::w_status_code::Aborted;\n                    },\n                    [](const auto&) -> quic::w_status { return quic::w_status_code::Success; }\n                });\n            };\n\n            BOOST_LEAF_CHECK(server.run(1234, server_listener_cb));\n\n            std::this_thread::sleep_for(std::chrono::seconds(1));\n\n            BOOST_LEAF_AUTO(client, quic::w_quic_client::make(quic::w_quic_client_config{\n                .alpn = \"sample\",\n                .settings = quic::w_settings{\n                    .idle_timeout_ms = 2000,\n                    .peer_bidi_stream_count = 1,\n                    .peer_unidi_stream_count = 1\n                },\n                .reg_config = quic::w_registration_config(\"client\")\n            }));\n\n            bool client_received = false;\n\n            auto client_stream_cb = [&](quic::w_stream& p_stream,\n                                        quic::w_stream_event& p_event) -> quic::w_status {\n                std::cout << \" [quic-client] stream callback: event: \" << p_event.name() << std::endl;\n                return p_event.visit(wolf::w_overloaded{\n                    [&](const quic::w_stream_event_start_complete&) {\n                        auto status = p_stream.send(\"Hello Server!\");\n                        BOOST_REQUIRE(status.succeeded());\n                        return quic::w_status_code::Success;\n                    },\n                    [&](const quic::w_stream_event_receive& p_ev) {\n                        BOOST_CHECK(p_ev.buffers().size() == 1);\n                        for (auto&& buffer : p_ev.buffers()) {\n                            auto str = std::string_view((const char*)buffer.data(), buffer.size());\n                            std::cout << \" [quic-client] stream: received: \" << str << std::endl;\n                            BOOST_CHECK(str == \"Hello Client!\");\n                        }\n                        client_received = true;\n                        return quic::w_status_code::Success;\n                    },\n                    [](const auto&) { return quic::w_status_code::Success; }\n                });\n            };\n\n            auto client_connection_cb = [&](quic::w_connection& p_conn,\n                                            quic::w_connection_event& p_event) -> quic::w_status {\n                std::cout << \" [quic-client] connection callback: event: \" << p_event.name() << std::endl;\n                return p_event.visit(wolf::w_overloaded{\n                    [&](const quic::w_connection_event_connected&) {\n                        auto stream = quic::w_stream::open(p_conn,\n                                             client_stream_cb,\n                                             quic::w_stream_open_flag::Unidirectional);\n                        BOOST_REQUIRE(stream);\n\n                        auto status = stream->start();\n                        BOOST_REQUIRE(status.succeeded());\n\n                        return quic::w_status_code::Success;\n                    },\n                    [&](const quic::w_connection_event_peer_stream_started& p_ev) {\n                        auto stream = p_ev.accept_stream(client_stream_cb);\n                        BOOST_REQUIRE(stream);\n                        return stream ? quic::w_status_code::Success\n                                      : quic::w_status_code::Aborted;\n                    },\n                    [](const auto&) { return quic::w_status_code::Success; }\n                });\n            };\n\n            BOOST_LEAF_CHECK(client.run(\"127.0.0.1\", 1234, client_connection_cb));\n\n            std::this_thread::sleep_for(std::chrono::seconds(3));\n\n            BOOST_CHECK(server_received);\n            BOOST_CHECK(client_received);\n\n            return {};\n        },\n        [](const w_trace& p_trace) {\n            BOOST_ERROR(p_trace.to_string());\n        },\n        []() {\n            BOOST_ERROR(\"unknown error occured.\");\n        }\n    );\n}\n\n#endif  // defined(WOLF_TEST) && defined(WOLF_STREAM_QUIC)\n"
  },
  {
    "path": "wolf/stream/test/rist.hpp",
    "content": "///*\n//    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n//    https://github.com/WolfEngine/WolfEngine\n//*/\n//\n//#if defined(WOLF_TEST) && defined(WOLF_STREAM_RIST)\n//\n//#pragma once\n//\n//#include <wolf.hpp>\n//#include <system/w_leak_detector.hpp>\n//#include <boost/test/included/unit_test.hpp>\n//\n//#include <stream/rist/w_rist.hpp>\n//\n//BOOST_AUTO_TEST_CASE(rist_data_block_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//  using w_rist_data_block = wolf::stream::rist::w_rist_data_block;\n//\n//  std::cout << \"rist_data_block_test is running\" << std::endl;\n//\n//  for (size_t i = 0; i < 5; i++) {\n//    std::string _msg = \"hello\";\n//    const auto _block = std::make_tuple((void *)_msg.data(), _msg.size());\n//\n//    auto _data_block = w_rist_data_block();\n//    _data_block.set(_block);\n//    auto _new_block = _data_block.get();\n//\n//    const auto new_msg = std::string_view(gsl::narrow_cast<const char *>(std::get<0>(_new_block)),\n//                                          std::get<1>(_new_block));\n//    BOOST_REQUIRE(new_msg == \"hello\");\n//  }\n//\n//  std::cout << \"rist_data_block_test is done\" << std::endl;\n//}\n//\n//BOOST_AUTO_TEST_CASE(rist_sender_receiver_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  std::cout << \"rist_sender_receiver_test is running\" << std::endl;\n//\n//  using w_rist = wolf::stream::rist::w_rist;\n//  using w_rist_data_block = wolf::stream::rist::w_rist_data_block;\n//  using namespace std::chrono_literals;\n//\n//  constexpr auto _timeout_in_sec = 5s;\n//  constexpr auto _mode = rist_profile::RIST_PROFILE_MAIN;\n//  constexpr auto _loss = 0;\n//\n//  std::thread thread_sender([&]() {\n//    boost::leaf::try_handle_all(\n//        [&]() -> boost::leaf::result<void> {\n//          // create a rist sender\n//          auto _sender =\n//              w_rist(rist_ctx_mode::RIST_SENDER_MODE, _mode, _loss, rist_log_level::RIST_LOG_DEBUG);\n//          auto _ret = _sender.init();\n//          BOOST_REQUIRE(_ret.has_error() == false);\n//\n//          constexpr auto _url =\n//              \"rist://\"\n//              \"127.0.0.1:1234?cname=wolf&rtt-max=10&rtt-min=1&secret=\"\n//              \"12345678&aes-type=256&bandwidth=6000\";\n//          _ret = _sender.connect(_url);\n//          BOOST_REQUIRE(_ret.has_error() == false);\n//\n//          const auto t0 = std::chrono::high_resolution_clock::now();\n//          auto _index = 0;\n//          static std::once_flag _once_flag;\n//\n//          for (;;) {\n//            std::string _msg = \"hello from RIST stream: #\" + std::to_string(_index++);\n//            const auto _block = std::make_tuple((void *)_msg.data(), _msg.size());\n//\n//            auto _data_block = w_rist_data_block();\n//            _data_block.set(_block);\n//\n//            auto _sent = _sender.send(_data_block);\n//            BOOST_REQUIRE(_sent.has_error() == false);\n//\n//            const auto t1 = std::chrono::high_resolution_clock::now();\n//            if (std::chrono::duration_cast<std::chrono::seconds>(t1 - t0) > _timeout_in_sec) {\n//              break;\n//            }\n//            std::this_thread::sleep_for(std::chrono::duration(1ms));\n//          }\n//\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          std::cout << \"got error :\" << p_trace << std::endl;\n//          BOOST_REQUIRE(false);\n//        },\n//        [] {\n//          std::cout << \"got an error!\" << std::endl;\n//          BOOST_ERROR(false);\n//        });\n//  });\n//\n//  std::thread thread_receiver([&]() {\n//    std::this_thread::sleep_for(std::chrono::duration(1s));\n//\n//    auto _receiver =\n//        w_rist(rist_ctx_mode::RIST_RECEIVER_MODE, _mode, _loss, rist_log_level::RIST_LOG_DEBUG);\n//    auto _ret = _receiver.init();\n//    BOOST_REQUIRE(_ret.has_error() == false);\n//\n//    _receiver.on_receiver_data_callback = [](_In_ const w_rist_data_block &p_data_block) {\n//      std::cout << p_data_block.to_string() << std::endl;\n//    };\n//\n//    constexpr auto url =\n//        \"rist://@\"\n//        \"127.0.0.1:1234?cname=wolf&rtt-max=10&rtt-min=1&secret=\"\n//        \"12345678&aes-type=256&bandwidth=6000\";\n//\n//    _ret = _receiver.connect(url);\n//    BOOST_REQUIRE(_ret.has_error() == false);\n//\n//    const auto t0 = std::chrono::high_resolution_clock::now();\n//    for (;;) {\n//      const auto t1 = std::chrono::high_resolution_clock::now();\n//      if (std::chrono::duration_cast<std::chrono::seconds>(t1 - t0) > _timeout_in_sec) {\n//        break;\n//      }\n//      std::this_thread::sleep_for(std::chrono::duration(1ms));\n//    }\n//  });\n//\n//  thread_sender.join();\n//  thread_receiver.join();\n//\n//  std::cout << \"rist_sender_receiver_test is done\" << std::endl;\n//}\n//\n//#endif"
  },
  {
    "path": "wolf/system/compression/w_lz4.cpp",
    "content": "#include \"w_lz4.hpp\"\n\n#ifdef WOLF_SYSTEM_LZ4\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#include <lz4.h>\n#include <DISABLE_ANALYSIS_END>\n\nusing w_lz4 = wolf::system::compression::w_lz4;\n\nstatic boost::leaf::result<int>\ns_check_input_len(_In_ const size_t p_src_size) noexcept {\n  if (p_src_size < LZ4_MAX_INPUT_SIZE) {\n    return 0;\n  }\n\n  std::string _src_size_msg;\n  try {\n    _src_size_msg = std::to_string(LZ4_MAX_INPUT_SIZE);\n  } catch (...) {\n  }\n  return W_FAILURE(std::errc::invalid_argument,\n                   \"source size is greater than LZ4_MAX_INPUT_SIZE: \" +\n                       _src_size_msg);\n}\n\nstatic std::vector<std::byte>\ns_shrink_to_fit(_In_ const std::vector<std::byte> &p_src, _In_ const size_t p_shrink_size) noexcept {\n  std::vector<std::byte> _dst;\n  _dst.resize(p_shrink_size);\n\n  std::copy(p_src.begin(), p_src.begin() + gsl::narrow_cast<int>(p_shrink_size), _dst.begin());\n  return _dst;\n}\n\nint w_lz4::get_compress_bound(_In_ int p_size) noexcept {\n  return LZ4_compressBound(p_size);\n}\n\nboost::leaf::result<std::vector<std::byte>>\nw_lz4::compress_default(_In_ const gsl::span<const std::byte> p_src) noexcept {\n  const auto _src_size = p_src.size();\n  if (_src_size == 0) {\n    return W_FAILURE(std::errc::invalid_argument, \"the source is empty\");\n  }\n\n  BOOST_LEAF_CHECK(s_check_input_len(_src_size));\n\n  const auto _dst_capacity = LZ4_compressBound(gsl::narrow_cast<int>(_src_size));\n  std::vector<std::byte> _tmp;\n  _tmp.resize(_dst_capacity);\n\n  const auto _bytes =\n      LZ4_compress_default(reinterpret_cast<const char *>(p_src.data()), reinterpret_cast<char *>(_tmp.data()),\n                           gsl::narrow_cast<int>(_src_size), _dst_capacity);\n  if (_bytes > 0) {\n    return s_shrink_to_fit(_tmp, _bytes);\n  }\n\n  return W_FAILURE(std::errc::operation_canceled,\n                   \"lz4 compress default failed\");\n}\n\nboost::leaf::result<std::vector<std::byte>>\nw_lz4::compress_fast(_In_ const gsl::span<const std::byte> p_src,\n                     _In_ const int p_acceleration) noexcept {\n  const auto _src_size = p_src.size();\n  if (_src_size == 0) {\n    return W_FAILURE(std::errc::invalid_argument, \"the source is empty\");\n  }\n\n  BOOST_LEAF_CHECK(s_check_input_len(_src_size));\n\n  const auto _dst_capacity = LZ4_compressBound(gsl::narrow_cast<int>(_src_size));\n  std::vector<std::byte> _tmp;\n  _tmp.resize(_dst_capacity);\n\n  const auto _bytes = LZ4_compress_fast(\n      reinterpret_cast<const char *>(p_src.data()), reinterpret_cast<char *>(_tmp.data()),\n      gsl::narrow_cast<int>(_src_size), _dst_capacity, p_acceleration);\n  if (_bytes > 0) {\n    return s_shrink_to_fit(_tmp, _bytes);\n  }\n\n  return W_FAILURE(std::errc::operation_canceled, \"lz4 compress fast failed\");\n}\n\nboost::leaf::result<std::vector<std::byte>>\nw_lz4::decompress(_In_ const gsl::span<const std::byte> p_src,\n                  _In_ const size_t p_max_retry) noexcept {\n  const auto _src_size = p_src.size();\n  if (_src_size == 0) {\n    return W_FAILURE(std::errc::invalid_argument, \"the source is empty\");\n  }\n\n  // we will increase our size per each step\n  std::vector<std::byte> _tmp;\n  auto _resize = _src_size * 2;\n\n#ifdef __clang\n#pragma unroll\n#endif\n  for (auto i = 0; i < p_max_retry; ++i) {\n    // resize it for next round\n    _tmp.resize(_resize);\n\n    const auto _bytes = LZ4_decompress_safe(\n        reinterpret_cast<const char *>(p_src.data()), reinterpret_cast<char *>(_tmp.data()),\n        gsl::narrow_cast<int>(_src_size), gsl::narrow_cast<int>(_tmp.size()));\n    if (_bytes > 0) {\n      return s_shrink_to_fit(_tmp, _bytes);\n    }\n\n    _resize *= 2;\n  }\n\n  std::string _max_retry_str;\n  try {\n    _max_retry_str = std::to_string(p_max_retry);\n  } catch (...) {\n  }\n  return W_FAILURE(std::errc::operation_canceled,\n                   \"could not decompress lz4 stream after \" + _max_retry_str);\n}\n\n#endif // WOLF_SYSTEM_LZ4\n"
  },
  {
    "path": "wolf/system/compression/w_lz4.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#ifdef WOLF_SYSTEM_LZ4\n\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system::compression {\n\nstruct w_lz4 {\n\n  /*\n   * get the size of compress bound\n   * @param p_size, the input size\n   * @returns the size of bound\n   */\n  W_API [[maybe_unused]] static int\n  get_compress_bound(_In_ int p_size) noexcept;\n\n  /*\n   * compress using the default mode of lz4\n   * @param p_src, the input source\n   * @returns the vector of compressed stream\n   */\n  W_API static boost::leaf::result<std::vector<std::byte>>\n  compress_default(_In_ const gsl::span<const std::byte> p_src) noexcept;\n\n  /*\n   * compress using the fast mode of lz4\n   * @param p_src, the input source\n   * @param p_acceleration, a value between 1 - 65536\n   * @returns the vector of compressed stream\n   */\n  W_API static boost::leaf::result<std::vector<std::byte>>\n  compress_fast(_In_ const gsl::span<const std::byte> p_src,\n                _In_ const int p_acceleration) noexcept;\n\n  /*\n   * decompress the compressed stream\n   * @param p_src, the input source\n   * @returns the vector of decompressed stream\n   */\n  W_API static boost::leaf::result<std::vector<std::byte>>\n  decompress(_In_ const gsl::span<const std::byte> p_src,\n             _In_ const size_t p_max_retry) noexcept;\n};\n} // namespace wolf::system::compression\n\n#endif // WOLF_SYSTEM_LZ4"
  },
  {
    "path": "wolf/system/compression/w_lzma.cpp",
    "content": "#include \"w_lzma.hpp\"\n\n#ifdef WOLF_SYSTEM_LZMA\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#include <Lzma2Enc.h>\n#include <Lzma2Dec.h>\n#include <LzmaDec.h>\n#include <LzmaEnc.h>\n#include <DISABLE_ANALYSIS_END>\n\nusing w_lzma = wolf::system::compression::w_lzma;\n\nconstexpr auto LZMA_HEADER_SRC_SIZE = 8;\nconstexpr auto MAX_HEADER_SIZE = 256 * 1024 * 1024;\n\nstatic void *s_lzma_alloc(ISzAllocPtr p_ptr, size_t p_size) noexcept {\n  std::ignore = p_ptr;\n  return malloc(p_size);\n}\nstatic void s_lzma_free(ISzAllocPtr p_ptr, void *p_addr) noexcept {\n  std::ignore = p_ptr;\n  free(p_addr);\n}\n\nconstexpr ISzAlloc s_alloc_funcs = {s_lzma_alloc, s_lzma_free};\n\nstatic void s_lzma_prop(_Inout_ CLzmaEncProps *p_prop, _In_ uint32_t p_level,\n                        _In_ int p_src_size) noexcept {\n  // set up properties\n  LzmaEncProps_Init(p_prop);\n\n  constexpr auto _min_dic_size = 1 << 12;\n  constexpr auto _max_dic_size = 3 << 29;\n  constexpr auto _max_level = 9;\n\n  constexpr auto _fb = 40;\n\n  if (p_src_size <= _min_dic_size) {\n    p_prop->dictSize = _min_dic_size;\n  } else if (p_src_size >= _max_dic_size) {\n    p_prop->dictSize = _max_dic_size;\n  } else {\n    p_prop->dictSize =\n        gsl::narrow_cast<uint32_t>(p_src_size); // smaller dictionary = faster!\n  }\n  p_prop->fb = _fb;\n\n  if (p_level >= _max_level) {\n    p_level = _max_level;\n  }\n  p_prop->level = p_level;\n}\n\nboost::leaf::result<std::vector<std::byte>>\nw_lzma::compress_lzma1(_In_ const gsl::span<const std::byte> p_src,\n                       _In_ uint32_t p_level) {\n  const auto _src_size = gsl::narrow_cast<int>(p_src.size());\n  if (_src_size == 0) {\n    return W_FAILURE(std::errc::invalid_argument, \"the source is empty\");\n  }\n\n  // set up properties\n  CLzmaEncProps _props = {};\n  s_lzma_prop(&_props, p_level, _src_size);\n\n  // prepare space for the encoded properties\n  size_t _props_size = LZMA_PROPS_SIZE;\n  std::array<std::byte, LZMA_PROPS_SIZE> _props_encoded = {};\n\n  // allocate some space for the compression output\n  // this is way more than necessary in most cases\n  auto _output_size_64 = gsl::narrow_cast<size_t>(_src_size) * 2;\n  if (_output_size_64 < 1024) {\n    _output_size_64 = 1024;\n  }\n\n  std::vector<std::byte> _tmp;\n  _tmp.resize(_output_size_64);\n\n  const auto _lzma_status =\n      LzmaEncode(reinterpret_cast<Byte *>(_tmp.data()), &_output_size_64,\n                 reinterpret_cast<const Byte *>(p_src.data()), p_src.size(),\n                 &_props, reinterpret_cast<Byte *>(_props_encoded.data()),\n                 &_props_size, 0, nullptr, &s_alloc_funcs, &s_alloc_funcs);\n\n  const auto _compressed_size =\n      _output_size_64 + LZMA_HEADER_SRC_SIZE + LZMA_PROPS_SIZE;\n\n  if (_lzma_status == SZ_OK) {\n    std::vector<std::byte> _dst;\n    _dst.reserve(_compressed_size);\n\n    // tricky: we have to generate the LZMA header\n    // 5 bytes properties + 8 byte uncompressed size\n    std::copy(_props_encoded.begin(), _props_encoded.begin() + LZMA_PROPS_SIZE,\n              std::back_inserter(_dst));\n\n    for (int i = 0; i < LZMA_HEADER_SRC_SIZE; i++) {\n      _dst.push_back(std::byte((_src_size >> (i * 8)) & 0xFF));\n    }\n\n    // copy the compressed size\n    std::copy(_tmp.begin(), _tmp.begin() + _output_size_64,\n              std::back_inserter(_dst));\n\n    return _dst;\n  }\n  return W_FAILURE(std::errc::operation_canceled, \"lzma1 compress failed\");\n}\n\nboost::leaf::result<std::vector<std::byte>>\nw_lzma::compress_lzma2(_In_ const gsl::span<const std::byte> p_src,\n                       _In_ uint32_t p_level) {\n  const auto _src_size = gsl::narrow_cast<int>(p_src.size());\n  if (_src_size == 0) {\n    return W_FAILURE(std::errc::invalid_argument, \"the source is empty\");\n  }\n\n  auto _enc_handler = Lzma2Enc_Create(&s_alloc_funcs, &s_alloc_funcs);\n  if (!_enc_handler) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"failed on creating lzma2 encoder\");\n  }\n\n  // set up properties\n  CLzmaEncProps _props_1{};\n  s_lzma_prop(&_props_1, p_level, _src_size);\n\n  CLzma2EncProps _props_2{};\n  Lzma2EncProps_Init(&_props_2);\n  _props_2.lzmaProps = _props_1;\n\n  const auto _props_status = Lzma2Enc_SetProps(_enc_handler, &_props_2);\n  if (_props_status != SZ_OK) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"failed on setting lzma2 encoder properties\");\n  }\n\n  // prepare space for the encoded properties\n  const auto properties = Lzma2Enc_WriteProperties(_enc_handler);\n  // allocate some space for the compression output\n  // this is way more than necessary in most cases.\n  auto _output_size_64 = gsl::narrow_cast<size_t>(_src_size) * 2;\n  if (_output_size_64 < 1024) {\n    _output_size_64 = 1024;\n  }\n\n  std::vector<std::byte> _tmp;\n  _tmp.resize(_output_size_64);\n\n  const auto _encode_status = Lzma2Enc_Encode2(\n      _enc_handler, nullptr, reinterpret_cast<Byte *>(_tmp.data()),\n      &_output_size_64, nullptr, reinterpret_cast<const Byte *>(p_src.data()),\n      _src_size, nullptr);\n  Lzma2Enc_Destroy(_enc_handler);\n\n  const auto _compressed_size =\n      _output_size_64 + LZMA_HEADER_SRC_SIZE + sizeof(properties);\n\n  if (_encode_status == SZ_OK) {\n    std::vector<std::byte> _dst;\n    _dst.reserve(_compressed_size);\n\n    /*\n        tricky: we have to generate the LZMA header\n        1 byte properties + 8 bytes uncompressed size\n    */\n    _dst.push_back(std::byte(properties));\n    for (int i = 0; i < LZMA_HEADER_SRC_SIZE; i++) {\n      _dst.push_back(std::byte((_src_size >> (i * 8)) & 0xFF));\n    }\n\n    // copy the compressed size\n    std::copy(_tmp.begin(), _tmp.begin() + _output_size_64,\n              std::back_inserter(_dst));\n\n    return _dst;\n  }\n  return W_FAILURE(std::errc::operation_canceled, \"lzma2 compress failed\");\n}\n\nboost::leaf::result<std::vector<std::byte>>\nw_lzma::decompress_lzma1(_In_ const gsl::span<const std::byte> p_src) {\n  const auto _src_size = p_src.size();\n\n  if (_src_size < LZMA_HEADER_SRC_SIZE + LZMA_PROPS_SIZE) {\n    return W_FAILURE(std::errc::invalid_argument, \"invalid lzma1 header size\");\n  }\n\n  // extract the size from the header\n  uint64_t _size_from_header = 0;\n  for (uint64_t i = 0; i < LZMA_HEADER_SRC_SIZE; i++) {\n    const auto _h1 = gsl::at(p_src, LZMA_PROPS_SIZE + i);\n    const auto _h2 = i * 8;\n    const auto _h3 = gsl::narrow_cast<uint64_t>(_h1 << _h2);\n    if (_h3 < std::numeric_limits<uint64_t>::max()) {\n      _size_from_header |= _h3;\n    }\n  }\n\n  std::vector<std::byte> _dst;\n  if (_size_from_header <= MAX_HEADER_SIZE) {\n    // allocate memory\n    _dst.resize(_size_from_header);\n\n    ELzmaStatus _lzma_status{};\n    size_t _proc_out_size = _size_from_header,\n           _proc_in_size = _src_size - LZMA_HEADER_SRC_SIZE + LZMA_PROPS_SIZE;\n    // decode via lzma\n    const auto _status = LzmaDecode(\n        reinterpret_cast<Byte *>(_dst.data()), &_proc_out_size,\n        reinterpret_cast<const Byte *>(\n            &gsl::at(p_src, LZMA_HEADER_SRC_SIZE + LZMA_PROPS_SIZE)),\n        &_proc_in_size, reinterpret_cast<const Byte *>(p_src.data()),\n        LZMA_PROPS_SIZE, LZMA_FINISH_END, &_lzma_status, &s_alloc_funcs);\n    // return on success\n    if (_status == SZ_OK && _proc_out_size == _size_from_header) {\n      return _dst;\n    }\n  }\n  return W_FAILURE(std::errc::operation_canceled, \"lzma1 decompress failed\");\n}\n\nboost::leaf::result<std::vector<std::byte>>\nw_lzma::decompress_lzma2(_In_ gsl::span<const std::byte> p_src) {\n  const auto _src_size = p_src.size();\n\n  if (_src_size < LZMA_HEADER_SRC_SIZE + sizeof(Byte)) {\n    return W_FAILURE(std::errc::invalid_argument, \"invalid lzma2 header size\");\n  }\n\n  // extract the size from the header\n  uint64_t _size_from_header = 0;\n  for (uint64_t i = 0; i < LZMA_HEADER_SRC_SIZE; i++) {\n    const auto _h1 = gsl::at(p_src, sizeof(Byte) + i);\n    const auto _h2 = i * 8;\n    const auto _h3 = gsl::narrow_cast<uint64_t>(_h1 << _h2);\n    if (_h3 < std::numeric_limits<uint64_t>::max()) {\n      _size_from_header |= _h3;\n    }\n  }\n\n  const auto _pre_out_size = _size_from_header * 2;\n  if (_size_from_header <= MAX_HEADER_SIZE) {\n    std::vector<std::byte> _dst;\n    _dst.resize(_size_from_header);\n\n    CLzma2Dec _dec{};\n    Lzma2Dec_Construct(&_dec);\n\n    auto _res = Lzma2Dec_Allocate(&_dec, 0, &s_alloc_funcs);\n    if (_res != SZ_OK) {\n      return W_FAILURE(std::errc::invalid_argument,\n                       \"could not allocate memory for lzma2 decoder\");\n    }\n\n    Lzma2Dec_Init(&_dec);\n    const auto properties = gsl::at(p_src, 0);\n    unsigned _out_pos = 0, _in_pos = LZMA_HEADER_SRC_SIZE + sizeof(properties);\n\n    ELzmaStatus _status = LZMA_STATUS_NOT_SPECIFIED;\n    constexpr uint32_t BUF_SIZE = 10240;\n\n    while (_out_pos < _pre_out_size) {\n      auto _dest_len = std::min(gsl::narrow_cast<uint64_t>(BUF_SIZE),\n                                _pre_out_size - _out_pos);\n      auto _src_len = std::min(gsl::narrow_cast<size_t>(BUF_SIZE),\n                               _src_size - gsl::narrow_cast<size_t>(_in_pos));\n\n      _res = Lzma2Dec_DecodeToBuf(\n          &_dec, reinterpret_cast<Byte *>(&gsl::at(_dst, _out_pos)), &_dest_len,\n          reinterpret_cast<const Byte *>(&gsl::at(p_src, _in_pos)), &_src_len,\n          (_out_pos + _dest_len == _size_from_header) ? LZMA_FINISH_END\n                                                      : LZMA_FINISH_ANY,\n          &_status);\n      if (_res != SZ_OK) {\n        return W_FAILURE(std::errc::invalid_argument,\n                         \"Lzma2Dec_DecodeToBuf failed\");\n      }\n\n      _in_pos += gsl::narrow_cast<uint32_t>(_src_len);\n      _out_pos += gsl::narrow_cast<uint32_t>(_dest_len);\n      if (_status == LZMA_STATUS_FINISHED_WITH_MARK) {\n        break;\n      }\n    }\n\n    Lzma2Dec_Free(&_dec, &s_alloc_funcs);\n\n    if (_out_pos == _size_from_header) {\n      return _dst;\n    }\n  }\n\n  return W_FAILURE(std::errc::operation_canceled, \"lzma2 decompress failed\");\n}\n\n#endif // WOLF_SYSTEM_LZMA"
  },
  {
    "path": "wolf/system/compression/w_lzma.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright � 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#ifdef WOLF_SYSTEM_LZMA\n\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system::compression {\n\nstruct w_lzma {\n\n  /*\n   * compress a stream via lzma1 algorithm\n   * @param p_src, the input source\n   * @param p_level, the level of compression\n   * @returns a vector of compressed stream\n   */\n  W_API static boost::leaf::result<std::vector<std::byte>>\n  compress_lzma1(_In_ const gsl::span<const std::byte> p_src,\n                 _In_ uint32_t p_level);\n\n  /*\n   * compress a stream via lzma2 algorithm\n   * @param p_src, the input source\n   * @param p_level, the level of compression\n   * @returns a vector of compressed stream\n   */\n  W_API static boost::leaf::result<std::vector<std::byte>>\n  compress_lzma2(_In_ const gsl::span<const std::byte> p_src,\n                 _In_ uint32_t p_level);\n\n  /*\n   * decompress a stream via lzma1 algorithm\n   * @param p_src, the input source\n   * @returns a vector of decompressed stream\n   */\n  W_API static boost::leaf::result<std::vector<std::byte>>\n  decompress_lzma1(_In_ const gsl::span<const std::byte> p_src);\n\n  /*\n   * decompress a stream via lzma2 algorithm\n   * @param p_src, the input source\n   * @returns a vector of decompressed stream\n   */\n  W_API static boost::leaf::result<std::vector<std::byte>>\n  decompress_lzma2(_In_ gsl::span<const std::byte> p_src);\n};\n} // namespace wolf::system::compression\n\n#endif // WOLF_SYSTEM_LZMA"
  },
  {
    "path": "wolf/system/db/w_postgresql.cpp",
    "content": "#include \"system/db/w_postgresql.hpp\"\n"
  },
  {
    "path": "wolf/system/db/w_postgresql.hpp",
    "content": "#ifdef WOLF_SYSTEM_POSTGRESQL\n\n#pragma once\n\n#include <memory>\n#include <string>\n#include <type_traits>\n\n#include <libpq-fe.h>\n\n#include <wolf.hpp>\n\nnamespace wolf::system::pgdb {\n\nnamespace internal {\n\n/**\n * @brief make a default instantiable delter callable out of compile-time known callable objects.\n *\n * intended to be used for C deleter functions, like `free`.\n * to be used with `std::unique_ptr` or similars.\n *\n * @tparam T type of the pointer which this deleter will be called with.\n * @tparam Func a callable object that takes a pointer of `T` as argument.\n */\ntemplate <typename T, auto Func>\nstruct c_type_deleter {\n    using pointer = std::remove_cvref_t<T>*;\n\n    constexpr auto operator()(pointer p_ptr) noexcept {\n        return Func(p_ptr);\n    }\n    constexpr auto operator()(pointer p_ptr) const noexcept {\n        return Func(p_ptr);\n    }\n};\n\ntemplate <typename T, auto DeleterFunc>\nusing c_type_raii = std::unique_ptr<T, c_type_deleter<T, DeleterFunc>>;\n\nusing dbconn = c_type_raii<PGconn, PQfinish>;\nusing dbresult = c_type_raii<PGresult, PQclear>;\nusing dbcancel = c_type_raii<PGcancel, PQfreeCancel>;\n\n/**\n * @brief check whether the given connection pointer is in error state.\n * @param p_conn internal connection pointer.\n * @return error or nothing.\n */\ninline auto dbconn_error_check(const dbconn& p_conn) -> boost::leaf::result<void>\n{\n    if (!p_conn) {\n        return W_FAILURE(std::errc::invalid_argument, \"connection is null.\");\n    }\n\n    switch (PQstatus(p_conn.get())) {\n    case CONNECTION_BAD:\n        return W_FAILURE(PQstatus(p_conn.get()), PQerrorMessage(p_conn.get()));\n\n    default:\n        return {};\n    }\n}\n\n/**\n * @brief check whether the given result pointer is in error state.\n * @param p_res internal result pointer.\n * @return error or nothing.\n */\ninline auto dbresult_error_check(const dbresult& p_res) -> boost::leaf::result<void>\n{\n    if (!p_res) {\n        return W_FAILURE(std::errc::invalid_argument,\n                         \"result is null.\");\n    }\n\n    switch (PQresultStatus(p_res.get())) {\n    case PGRES_FATAL_ERROR:\n    case PGRES_NONFATAL_ERROR:\n    case PGRES_BAD_RESPONSE:\n        return W_FAILURE(PQresultStatus(p_res.get()), PQresultErrorMessage(p_res.get()));\n\n    default:\n        return {};\n    }\n}\n\n/// basic converters\n\ntemplate <typename T> requires std::is_integral_v<T>\ninline auto to_string(T p_value) -> std::string\n{\n    return std::to_string(p_value);\n}\n\ninline auto to_string(const char* const p_value) -> std::string\n{\n    return std::string(p_value);\n}\n\ninline auto to_string(const std::string& p_value) -> std::string\n{\n    return p_value;\n}\n\ninline auto to_string(std::string&& p_value) -> std::string\n{\n    return p_value;\n}\n\ntemplate <typename T>\n    requires std::is_integral_v<T>\ninline auto from_string(T* p_ptr, const char* p_str) -> boost::leaf::result<void>\n{\n    auto [errptr, errcode] = std::from_chars(p_str, p_str + strlen(p_str), *p_ptr);\n    if (errcode != std::errc()) {\n        return W_FAILURE(errcode, \"could not convert given string to given integral type.\");\n    }\n\n    return {};\n}\n\ninline auto from_string(std::string* p_ptr, const char* p_str) -> boost::leaf::result<void>\n{\n    *p_ptr = std::string(p_str);\n    return {};\n}\n\n}  // namespace internal\n\n// forward declares mostly for friend statements.\nclass w_pgdb_conection;\nclass w_pgdb_execresult;\nclass w_pgdb_queryresult;\n\n/**\n * @brief single convertible record/row.\n */\nclass w_pgdb_record {\n    friend w_pgdb_queryresult;\n\npublic:\n    /**\n     * @brief get raw string at given field index.\n     * @return raw c string value at given field index, it might be null.\n     */\n    auto at(std::size_t p_field_index) const noexcept -> const char*\n    {\n        return PQgetvalue(_res_ptr.get(), static_cast<int>(_record_index), static_cast<int>(p_field_index));\n    }\n\n    /**\n     * @brief count of fields.\n     */\n    auto size() const noexcept -> std::size_t\n    {\n        return PQnfields(_res_ptr.get());\n    }\n\n    /**\n     * @brief convert fields into given types and store into pointed objects.\n     * @param ptrs pointers to objects to read.\n     */\n    template <typename ...Ts>\n    auto scan(Ts* ...p_ptrs) -> boost::leaf::result<void>\n    {\n        if (sizeof...(Ts) != PQnfields(_res_ptr.get())) {\n            return W_FAILURE(std::errc::invalid_argument,\n                             \"given params to scan are more than available record fields.\");\n        }\n\n        if constexpr (sizeof...(Ts) == 0) {\n            return {};\n        } else {\n            return scan(0, p_ptrs...);\n        }\n    }\n\nprivate:\n    template <typename T>\n    auto scan(std::size_t p_field_index, T* p_ptr) -> boost::leaf::result<void>\n    {\n        return scan_field_into(p_field_index, p_ptr);\n    }\n\n    template <typename T, typename U, typename ...Rest>\n    auto scan(std::size_t p_field_index, T* p_first, U* p_second, Rest* ...p_rest)\n        -> boost::leaf::result<void>\n    {\n        BOOST_LEAF_CHECK(scan_field_into(p_field_index, p_first));\n\n        return scan(p_field_index + 1, p_second, p_rest...);\n    }\n\n    template <typename T>\n    auto scan_field_into(std::size_t p_field_index, T* p_ptr) -> boost::leaf::result<void>\n    {\n        auto str_value = PQgetvalue(_res_ptr.get(), _record_index, p_field_index);\n        if (!str_value) {\n            return W_FAILURE(std::errc::invalid_argument, \"field could not be retrieved.\");\n        }\n\n        BOOST_LEAF_CHECK(internal::from_string(p_ptr, str_value));\n\n        return {};\n    }\n\n    w_pgdb_record(const internal::dbresult& p_res, std::size_t p_index) noexcept\n        : _res_ptr(p_res)\n        , _record_index(p_index)\n    {}\n\n    const internal::dbresult& _res_ptr;\n    const std::size_t _record_index = 0;\n};\n\n/**\n * @brief sql query result from sql command that does yield back values.\n */\nclass w_pgdb_queryresult {\n    friend w_pgdb_execresult;\n\npublic:\n    ~w_pgdb_queryresult() { done(); }\n\n    // move-only\n    w_pgdb_queryresult(const w_pgdb_queryresult&) = delete;\n    w_pgdb_queryresult(w_pgdb_queryresult&& p_other) noexcept\n        : _conn_ptr(p_other._conn_ptr)\n        , _res_ptr(p_other._res_ptr.release())\n        , _row_index(std::exchange(p_other._row_index, 0))\n    {}\n\n    w_pgdb_queryresult& operator=(const w_pgdb_queryresult&) = delete;\n    w_pgdb_queryresult& operator=(w_pgdb_queryresult&& p_other) noexcept\n    {\n        std::swap(_conn_ptr, p_other._conn_ptr);\n        std::swap(_res_ptr, p_other._res_ptr);\n        std::swap(_row_index, p_other._row_index);\n        return *this;\n    };\n\n    /**\n     * @brief count of records in the result.\n     */\n    auto size() const noexcept -> std::size_t\n    {\n        return PQntuples(_res_ptr.get());\n    }\n\n    /**\n     * @brief count of fields in each record.\n     */\n    auto field_count() const noexcept -> std::size_t\n    {\n        return PQnfields(_res_ptr.get());\n    }\n\n    /**\n     * @brief name of the field at given index.\n     * @param p_index field index.\n     */\n    auto field_name_at(std::size_t p_index) const noexcept -> const char*\n    {\n        return PQfname(_res_ptr.get(), static_cast<int>(p_index));\n    }\n\n    /**\n     * @brief whether the result contains or doesn't contain any records.\n     */\n    auto is_empty() -> bool\n    {\n        auto status = PQresultStatus(_res_ptr.get());\n        return (status != PGRES_TUPLES_OK && status != PGRES_SINGLE_TUPLE) || size() == 0;\n    }\n\n    /**\n     * @brief process each record by given handler.\n     *\n     * until the handler return error or there wouldn't be any more result.\n     *\n     * @param p_handler callable to pass each record to and returns a boost leaf result.\n     * @return count of processed records.\n     */\n    template <typename F>\n    auto on_each(F&& p_handler) -> boost::leaf::result<std::size_t>\n    {\n        if (!_res_ptr) {\n            return W_FAILURE(std::errc::operation_canceled, \"result doesn't exist or has been consumed already.\");\n        }\n\n        std::size_t row_index = 0;\n\n        const auto size = PQntuples(_res_ptr.get());\n\n        while (row_index < size) {\n            auto record = w_pgdb_record(_res_ptr, row_index);\n\n            BOOST_LEAF_CHECK(p_handler(record));\n\n            if (PQresultStatus(_res_ptr.get()) == PGRES_SINGLE_TUPLE) {\n                _res_ptr.reset(PQgetResult(_conn_ptr.get()));\n            }\n\n            ++row_index;\n        }\n\n        return row_index;\n    }\n\n    /**\n     * @brief process a single record by given handler.\n     * @param p_handler callable to pass each record to and returns a boost leaf result.\n     * @return error or nothing.\n     */\n    template <typename F>\n    auto on_single(F&& p_handler) -> boost::leaf::result<void>\n    {\n        if (!_res_ptr) {\n            return W_FAILURE(std::errc::operation_canceled,\n                             \"result doesn't exist or has been consumed already.\");\n        }\n\n        auto record = w_pgdb_record(_res_ptr, _row_index);\n\n        BOOST_LEAF_CHECK(p_handler(record));\n\n        if (PQresultStatus(_res_ptr.get()) == PGRES_SINGLE_TUPLE) {\n            _res_ptr.reset(PQgetResult(_conn_ptr.get()));\n        }\n\n        _row_index++;\n\n        return {};\n    }\n\n    /**\n     * @brief cancel the ongoing query.\n     * @return error or nothing.\n     */\n    auto cancel() -> boost::leaf::result<void>\n    {\n        auto cancel_req = internal::dbcancel(PQgetCancel(_conn_ptr.get()));\n        if (!cancel_req) {\n            return W_FAILURE(PQstatus(_conn_ptr.get()), \"could not create cancellation object.\");\n        }\n\n        // stack is much faster and safer, heap alloc isn't required if we don't hit error.\n        constexpr auto errbuf_size = 255;\n        char errbuf[errbuf_size + 1] = { 0 };\n\n        if (PQcancel(cancel_req.get(), errbuf, errbuf_size) <= 0) {\n            return W_FAILURE(PQstatus(_conn_ptr.get()), std::string(errbuf));\n        }\n\n        return {};\n    }\n\n    /**\n     * @brief consume the remaining of the result,\n     *        so new command/queries on the connection can be made.\n     */\n    void done()\n    {\n        while (_res_ptr) {\n            _res_ptr.reset(PQgetResult(_conn_ptr.get()));\n        }\n    }\n\nprivate:\n    explicit w_pgdb_queryresult(internal::dbconn& p_conn, internal::dbresult&& p_result)\n        : _conn_ptr(p_conn)\n        , _res_ptr(std::move(p_result))\n    {}\n\n    auto raw() noexcept -> internal::dbresult& { return _res_ptr; }\n    auto raw() const noexcept -> const internal::dbresult& { return _res_ptr; }\n\n    internal::dbconn& _conn_ptr;\n    internal::dbresult _res_ptr{nullptr};\n    std::size_t _row_index = 0; //< count of so far read rows.\n};\n\n/**\n * @brief sql execution result from sql command that doesn't yield back values.\n */\nclass w_pgdb_execresult {\n    friend w_pgdb_conection;\n\npublic:\n    ~w_pgdb_execresult() { done(); }\n\n    // move-only\n    w_pgdb_execresult(const w_pgdb_execresult&) = delete;\n    w_pgdb_execresult(w_pgdb_execresult&& p_other) noexcept\n        : _conn_ptr(p_other._conn_ptr)\n        , _res_ptr(p_other._res_ptr.release())\n    {}\n\n    w_pgdb_execresult& operator=(const w_pgdb_execresult&) = delete;\n    w_pgdb_execresult& operator=(w_pgdb_execresult&& p_other) noexcept\n    {\n        std::swap(_conn_ptr, p_other._conn_ptr);\n        std::swap(_res_ptr, p_other._res_ptr);\n        return *this;\n    };\n\n    // since two internal::dbresult can't exist at the same time,\n    // create w_pgdb_queryresult and dispose *this.\n    auto as_query() && -> w_pgdb_queryresult\n    {\n        return w_pgdb_queryresult(_conn_ptr, std::move(_res_ptr));\n    }\n\n    /**\n     * @brief consume the remaining of the result,\n     *        so new command/queries on the connection can be made.\n     */\n    void done()\n    {\n        while (_res_ptr) {\n            _res_ptr.reset(PQgetResult(_conn_ptr.get()));\n        }\n    }\n\nprivate:\n    explicit w_pgdb_execresult(internal::dbconn& p_conn, internal::dbresult&& p_res)\n        : _conn_ptr(p_conn)\n        , _res_ptr(std::move(p_res))\n    {}\n\n    auto raw() noexcept -> internal::dbresult& { return _res_ptr; }\n    auto raw() const noexcept -> const internal::dbresult& { return _res_ptr; }\n\n    internal::dbconn& _conn_ptr;\n    internal::dbresult _res_ptr{nullptr};\n};\n\n/**\n * a single connection to database to execute/query one at a time.\n *\n * create a connection by calling one of static factory methods like `make`.\n */\nclass w_pgdb_conection {\npublic:\n    w_pgdb_conection(const w_pgdb_conection&) = delete;\n    w_pgdb_conection(w_pgdb_conection&& other) noexcept\n        : _conn_ptr(other._conn_ptr.release())\n    {}\n\n    w_pgdb_conection& operator=(const w_pgdb_conection&) = delete;\n    w_pgdb_conection& operator=(w_pgdb_conection&& other) noexcept\n    {\n        std::swap(_conn_ptr, other._conn_ptr);\n        return *this;\n    };\n\n    ~w_pgdb_conection() { _conn_ptr.reset(); }\n\n    /**\n     * @brief make a connection by given key-value parameters.\n     *\n     * @note each pair's key and value must be convertible to `const char*`.\n     * @note valid param details can be found at: https://www.postgresql.org/docs/current/libpq-connect.html\n     *\n     * @param p_params pairs of key-value parameters. (e.g. {\"host\", \"localhost\"}, {\"port\", \"26257\"})\n     * @return database connection or error.\n     */\n    template <typename ...Ts, typename ...Us>\n    static auto make(const std::pair<Ts, Us>& ...p_params) -> boost::leaf::result<w_pgdb_conection>\n    {\n        const auto params_count = sizeof...(Ts);\n\n        const char* keywords[params_count + 1] = { static_cast<const char*>(p_params.first)..., nullptr };\n        const char* values[params_count + 1] = { static_cast<const char*>(p_params.second)..., nullptr };\n\n        auto dbconn = internal::dbconn(PQconnectdbParams(keywords, values, 0));\n\n        BOOST_LEAF_CHECK(internal::dbconn_error_check(dbconn));\n\n        return w_pgdb_conection(std::move(dbconn));\n    }\n\n    /**\n     * @brief make a connection by given connection string url.\n     *\n     * for example: postgre://admin:admin@localhost:26257/defaultdb\n     *\n     * @param p_conn_str connection string url.\n     * @return database connection or error.\n     */\n    static auto make(const char* p_conn_str) -> boost::leaf::result<w_pgdb_conection>\n    {\n        auto conn = internal::dbconn(PQconnectdb(p_conn_str));\n\n        BOOST_LEAF_CHECK(internal::dbconn_error_check(conn));\n\n        return w_pgdb_conection(std::move(conn));\n    }\n\n    /**\n     * @brief execute the given sql command with given sql parameters.\n     *\n     * @note params will be converted to string by an internal converter for simple types.\n     *       if your type isn't supported, convert to string then pass it to this method.\n     *\n     * @param p_sqlstr sql command.\n     * @param p_params sql command's parameters. (if there are any)\n     * @return command result or error.\n     */\n    template <typename ...Args>\n    auto execute(const char* p_sqlstr, Args&& ...p_params) -> boost::leaf::result<w_pgdb_execresult>\n    {\n        constexpr std::size_t arg_count = sizeof...(Args);\n\n        // avoid complicated process of making params when none are given.\n        if constexpr (arg_count == 0) {\n            if (PQsendQuery(_conn_ptr.get(), p_sqlstr) <= 0) {\n                return W_FAILURE(PQstatus(_conn_ptr.get()), PQerrorMessage(_conn_ptr.get()));\n            }\n        } else {\n            // currently raw data isn't supported, and it's only text/string.\n            // IIFE for compile-time stack array allocation and loop-free initialization.\n            int res = [&](std::same_as<std::string> auto&& ...p_str_params) {\n                const char* string_array[arg_count] = { (p_str_params.c_str())... };\n\n                int length_array[arg_count] = { static_cast<int>(p_str_params.size())... };\n\n                return PQsendQueryParams(\n                            _conn_ptr.get(),\n                            p_sqlstr,\n                            arg_count,\n                            nullptr,  // infer types, they're not determined.\n                            string_array,\n                            length_array,\n                            nullptr,  // only nul-terminated c strings (text), binary isn't supported.\n                            0\n                       );\n            }(internal::to_string(std::forward<Args>(p_params))...);\n\n            if (res <= 0) {\n                return W_FAILURE(PQstatus(_conn_ptr.get()), PQerrorMessage(_conn_ptr.get()));\n            }\n        }\n\n        // to make sure the result will be terminated/disposed correctly on error,\n        // otherwise the connection will still hold the result and next execute won't work.\n        auto dbres = w_pgdb_execresult(_conn_ptr, internal::dbresult(PQgetResult(_conn_ptr.get())));\n        BOOST_LEAF_CHECK(internal::dbresult_error_check(dbres.raw()));\n\n        return dbres;\n    }\n\n    /**\n     * @brief execute the given sql query with given sql parameters.\n     *\n     * @note params will be converted to string by an internal converter for simple types.\n     *       if your type isn't supported, convert to string then pass it to this method.\n     *\n     * @param p_sqlstr sql query.\n     * @param p_params sql query's parameters. (if there are any)\n     * @return query result or error.\n     */\n    template <typename ...Args>\n    auto query(const char* p_sqlstr, Args&& ...p_args) -> boost::leaf::result<w_pgdb_queryresult>\n    {\n        BOOST_LEAF_AUTO(res, execute(p_sqlstr, std::forward<Args>(p_args)...));\n        return std::move(res).as_query();\n    }\n\n    /**\n     * @brief execute the given sql query with given sql parameters in streaming mode.\n     *\n     * the result records will be fetched one at a time to be processed,\n     * instead of waiting for all records to be retrieved.\n     *\n     * @note params will be converted to string by an internal converter for simple types.\n     *       if your type isn't supported, convert to string then pass it to this method.\n     *\n     * @param p_sqlstr sql query.\n     * @param p_params sql query's parameters. (if there are any)\n     * @return query result or error.\n     */\n    template <typename ...Args>\n    auto stream_query(const char* p_sqlstr, Args&& ...p_args) -> boost::leaf::result<w_pgdb_queryresult>\n    {\n        BOOST_LEAF_AUTO(res, execute(p_sqlstr, std::forward<Args>(p_args)...));\n\n        if (PQsetSingleRowMode(_conn_ptr.get()) <= 0) {\n            return W_FAILURE(PQstatus(_conn_ptr.get()), PQerrorMessage(_conn_ptr.get()));\n        }\n\n        return std::move(res).as_query();\n    }\n\nprivate:\n    explicit w_pgdb_conection(internal::dbconn&& p_conn) : _conn_ptr(std::move(p_conn)) {}\n\n    auto raw() noexcept -> internal::dbconn& { return _conn_ptr; }\n    auto raw() const noexcept -> const internal::dbconn& { return _conn_ptr; }\n\n    internal::dbconn _conn_ptr;\n};\n\n}  // namespace wolf::system::pgdb\n\n#endif  // WOLF_SYSTEM_POSTGRESQL\n"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_client.hpp",
    "content": "#pragma once\n\n#ifdef WOLF_SYSTEM_GAMEPAD_CLIENT\n\n#include \"w_gamepad_client_types.hpp\"\n#include <vector>\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system::gamepad {\nclass w_gamepad_client {\npublic:\n  W_API static boost::leaf::result<int> init() noexcept;\n\n  W_API static bool\n  get_events(_Inout_ w_gamepad_client_event &p_event) noexcept {\n    if (_events.empty()) {\n      return false;\n    }\n    p_event = _events.back();\n    _events.pop_back();\n    return true;\n  }\n\n  //W_API static void update() noexcept;\n\n  // W_API static void fini() noexcept;\n\nprivate:\n  // LIFO queue of events\n  static std::vector<w_gamepad_client_event> _events;\n};\n} // namespace wolf::system::gamepad\n\n#endif\n"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_client_emc.cpp",
    "content": "#if defined(WOLF_SYSTEM_GAMEPAD_CLIENT) && defined(EMSCRIPTEN)\n\n#include \"w_gamepad_client.hpp\"\n#include \"w_gamepad_client_keymap.hpp\"\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#include <emscripten/html5.h>\n#include <DISABLE_ANALYSIS_END>\n\nusing w_gamepad_client = wolf::system::gamepad::w_gamepad_client;\nusing w_gamepad_event = wolf::system::gamepad::w_gamepad_event;\n\nstd::vector<EmscriptenGamepadEvent> gamepads;\nstd::vector<w_gamepad_event> w_gamepad_client::_events;\n\nEM_BOOL gamepadconnected_callback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) {\n  gamepads.push_back(*gamepadEvent);\n  reinterpret_cast<w_gamepad_client *>(userData)->update();\n\n  return EM_TRUE;\n}\n\nEM_BOOL gamepaddisconnected_callback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) {\n  std::erase_if(gamepads, [gamepadEvent](const auto &e) {\n    return gamepadEvent->index == e.index;\n  });\n\n  return EM_TRUE;\n}\n\nboost::leaf::result<int> w_gamepad_client::init() noexcept {\n  // TODO: callback registration may fail, check for EMSCRIPTEN_RESULT_SUCCESS\n  emscripten_set_gamepadconnected_callback(this, EM_TRUE,\n                                           gamepadconnected_callback);\n  emscripten_set_gamepaddisconnected_callback(this, EM_TRUE,\n                                              gamepaddisconnected_callback);\n\n  return S_OK;\n}\n\nvoid w_gamepad_client::update() {\n  emscripten_sample_gamepad_data();\n\n  for (auto &gamepad : gamepads) {\n    EmscriptenGamepadEvent gamepadState;\n    auto result = emscripten_get_gamepad_status(gamepad.index, &gamepadState);\n\n    if (result != EMSCRIPTEN_RESULT_SUCCESS) {\n      continue;\n    }\n\n    if (gamepadState.timestamp != 0 &&\n        gamepadState.timestamp == gamepad.timestamp) {\n      continue;\n    }\n\n    for (int i = 0; i < gamepadState.numButtons; i++) {\n      if (gamepad.digitalButton[i] == gamepadState.digitalButton[i]) {\n        continue;\n      }\n\n      auto state = gamepadState.digitalButton[i]\n                       ? w_gamepad_state_type::PRESSED\n                       : w_gamepad_state_type::RELEASED;\n      w_gamepad_button button{.type = w_gamepad_event_type::BUTTON,\n                              .which = (std::uint32_t)gamepad.index,\n                              .button = w_gamepad_button_map[i],\n                              .state = state};\n      w_gamepad_event event{.button = button};\n      _events.emplace_back(event);\n    }\n\n    for (int i = 0; i < gamepadState.numAxes; i++) {\n      if (gamepad.axis[i] == gamepadState.axis[i]) {\n        continue;\n      }\n\n      auto value = (std::int16_t)(32767. * gamepadState.axis[i]);\n      w_gamepad_axis axis{.type = w_gamepad_event_type::AXIS,\n                          .which = (std::uint32_t)gamepad.index,\n                          .axis = w_gamepad_axis_map[i],\n                          .value = value};\n      w_gamepad_event event{.axis = axis};\n      _events.emplace_back(event);\n    }\n\n    gamepad = gamepadState;\n  }\n}\n\nvoid w_gamepad_client::fini() noexcept {\n  this->gamepads.clear();\n  this->_events.clear();\n}\n\n#endif //  defined(WOLF_SYSTEM_GAMEPAD) && defined(EMSCRIPTEN)"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_client_keymap.hpp",
    "content": "#ifdef WOLF_SYSTEM_GAMEPAD_CLIENT\n\n#pragma once\n\n#include \"w_gamepad_client_types.hpp\"\n\nnamespace wolf::system::gamepad {\n\nstatic w_gamepad_client_button_type w_gamepad_button_map[] = {\n    w_gamepad_client_button_type::A,\n    w_gamepad_client_button_type::B,\n    w_gamepad_client_button_type::X,\n    w_gamepad_client_button_type::Y,\n    w_gamepad_client_button_type::left_shoulder,\n    w_gamepad_client_button_type::right_shoulder,\n    w_gamepad_client_button_type::paddle_1,\n    w_gamepad_client_button_type::paddle_2,\n    w_gamepad_client_button_type::back,\n    w_gamepad_client_button_type::start,\n    w_gamepad_client_button_type::left_stick,\n    w_gamepad_client_button_type::right_stick,\n    w_gamepad_client_button_type::dpad_up,\n    w_gamepad_client_button_type::dpad_down,\n    w_gamepad_client_button_type::dpad_left,\n    w_gamepad_client_button_type::dpad_right,\n    w_gamepad_client_button_type::guide,\n};\n\nstatic w_gamepad_client_axis_type w_gamepad_axis_map[] = {\n    w_gamepad_client_axis_type::left_x,\n    w_gamepad_client_axis_type::left_y,\n    w_gamepad_client_axis_type::right_x,\n    w_gamepad_client_axis_type::right_y,\n};\n\n} // namespace wolf::system::gamepad\n\n#endif\n"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_client_sdl.cpp",
    "content": "#if defined(WOLF_SYSTEM_GAMEPAD_CLIENT) && !defined(EMSCRIPTEN)\n\n#include \"w_gamepad_client.hpp\"\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#include <SDL3/SDL.h>\n#include <DISABLE_ANALYSIS_END>\n\nusing w_gamepad_client = wolf::system::gamepad::w_gamepad_client;\nusing w_gamepad_client_event = wolf::system::gamepad::w_gamepad_client_event;\n\nstd::vector<SDL_Gamepad*> s_controllers;\nstd::vector<w_gamepad_client_event> w_gamepad_client::_events;\n\nstatic std::string s_get_sdl_last_error_msg() noexcept {\n  std::string _error_msg;\n  _error_msg.reserve(W_MAX_PATH);\n  SDL_GetErrorMsg(_error_msg.data(), W_MAX_PATH);\n  return _error_msg;\n}\n\nboost::leaf::result<int> w_gamepad_client::init() noexcept {\n  const auto _ret = SDL_Init(SDL_INIT_GAMEPAD);\n  if (_ret != 0) {\n    return W_FAILURE(_ret,\n                     \"could not initialize the SDL for gamepad. SDL error: \" +\n                         s_get_sdl_last_error_msg());\n  }\n\n  int _number_of_joysticks = -1;\n  const auto _joysticks = SDL_GetJoysticks(&_number_of_joysticks);\n  if (_number_of_joysticks <= 0) {\n    return W_FAILURE(_ret, \"could not find any joystick. SDL error: \" +\n                               s_get_sdl_last_error_msg());\n  }\n\n  for (size_t i = 0; i < _number_of_joysticks; i++) {\n    if (SDL_IsGamepad(_joysticks[i])) {\n      s_controllers.push_back(SDL_OpenGamepad(_joysticks[i]));\n    }\n  }\n  return S_OK;\n}\n\n//void w_gamepad_client::update() noexcept {\n//  SDL_Event sdl_event = {};\n//  w_gamepad_client_button button{.type = w_gamepad_client_event_type::button};\n//  w_gamepad_client_axis axis{.type = w_gamepad_client_event_type::axis};\n//  w_gamepad_client_event _event = {};\n//  while (SDL_PollEvent(&sdl_event)) {\n//    switch (sdl_event.type) {\n//    default:\n//      break;\n//    case SDL_GAMEPAD_BUTTON_DPAD_DOWN:\n//    case SDL_GAMEPAD_BUTTON_DPAD_UP: {\n//      button.which = sdl_event.cbutton.which;\n//      button.button =\n//          gsl::narrow_cast<w_gamepad_client_button_type>(sdl_event.cbutton.button + 1);\n//      button.state = sdl_event.cbutton.state ? w_gamepad_client_state_type::pressed\n//                                             : w_gamepad_client_state_type::released;\n//      _event.button = button;\n//      _events.emplace_back(_event);\n//      break;\n//    }\n//    case SDL_EVENT_GAMEPAD_AXIS_MOTION: {\n//      axis.which = sdl_event.caxis.which;\n//      axis.axis =\n//          gsl::narrow_cast<w_gamepad_client_axis_type>(sdl_event.caxis.axis + 1);\n//      axis.value = sdl_event.caxis.value;\n//      _event.axis = axis;\n//      _events.emplace_back(_event);\n//      break;\n//    }\n//    case SDL_EVENT_GAMEPAD_ADDED: {\n//      s_controllers.push_back(SDL_OpenGamepad(sdl_event.cdevice.which));\n//      break;\n//    }\n//    case SDL_EVENT_GAMEPAD_REMOVED: {\n//      auto controller = SDL_GetGamepadFromInstanceID(sdl_event.cdevice.which);\n//      auto _iter =\n//          std::find(s_controllers.cbegin(), s_controllers.cend(), controller);\n//      SDL_CloseGamepad(*_iter);\n//      s_controllers.erase(_iter);\n//      break;\n//    }\n//    }\n//  }\n//}\n//\n//void w_gamepad_client::fini() noexcept {\n//  for (auto _iter : s_controllers) {\n//    if (_iter) {\n//      SDL_CloseGamepad(_iter);\n//    }\n//  }\n//  s_controllers.clear();\n//  SDL_Quit();\n//}\n\n#endif // defined(WOLF_SYSTEM_GAMEPAD) && !defined(EMSCRIPTEN)"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_client_types.hpp",
    "content": "#ifdef WOLF_SYSTEM_GAMEPAD_CLIENT\n\n#pragma once\n\n#include <cstdint>\n\nnamespace wolf::system::gamepad {\n\nenum class w_gamepad_client_event_type { button, axis, max };\n\nenum class w_gamepad_client_state_type { released, pressed, max };\n\nenum class w_gamepad_client_button_type {\n  A,\n  B,\n  X,\n  Y,\n  back,\n  guide,\n  start,\n  left_stick,\n  right_stick,\n  left_shoulder,\n  right_shoulder,\n  dpad_up,\n  dpad_down,\n  dpad_left,\n  dpad_right,\n  // Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro\n  // capture button, Amazon Luna microphone button\n  misc_1,\n  // Xbox Elite paddle P1\n  paddle_1,\n  // Xbox Elite paddle P3\n  paddle_2,\n  // Xbox Elite paddle P2\n  paddle_3,\n  // Xbox Elite paddle P4\n  paddle_4,\n  // PS4/PS5 touchpad button\n  touch_pad,\n  max\n};\n\nenum class w_gamepad_client_axis_type {\n  left_x,\n  left_y,\n  right_x,\n  right_y,\n  trigger_left,\n  trigger_right,\n  max\n};\n\nstruct w_gamepad_client_button {\n  w_gamepad_client_event_type type;\n  std::uint32_t which;\n  w_gamepad_client_button_type button;\n  w_gamepad_client_state_type state;\n};\n\nstruct w_gamepad_client_axis {\n  w_gamepad_client_event_type type;\n  std::uint32_t which;\n  w_gamepad_client_axis_type axis;\n  std::int16_t value;\n};\n\nunion w_gamepad_client_event {\n  w_gamepad_client_event_type type;\n  w_gamepad_client_button button;\n  w_gamepad_client_axis axis;\n};\n\n} // namespace wolf::system::gamepad\n\n#endif"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_virtual.cpp",
    "content": "#if defined(WOLF_SYSTEM_GAMEPAD_VIRTUAL) && !defined(EMSCRIPTEN)\n\n#include \"w_gamepad_virtual.hpp\"\n\nusing w_gamepad_virtual = wolf::system::gamepad::w_gamepad_virtual;\n\nw_gamepad_virtual::w_gamepad_virtual(\n    _In_ std::shared_ptr<w_gamepad_virtual_bus> p_vigem_bus) noexcept\n    : _bus(std::move(p_vigem_bus)) {}\n\nw_gamepad_virtual::~w_gamepad_virtual() { _release(); }\n\nw_gamepad_virtual::w_gamepad_virtual(_Inout_ w_gamepad_virtual &&p_other) noexcept {\n  _move(std::move(p_other));\n}\n\nw_gamepad_virtual &w_gamepad_virtual::operator=(_Inout_ w_gamepad_virtual &&p_other) noexcept {\n  _move(std::move(p_other));\n  return *this;\n}\n\nvoid w_gamepad_virtual::_move(_Inout_ w_gamepad_virtual &&p_other) noexcept {\n  if (this == &p_other)\n    return;\n\n  _release();\n\n  this->_bus = std::move(p_other._bus);\n  this->_target = std::exchange(p_other._target, nullptr);\n  this->_last_error = p_other._last_error;\n}\n\nboost::leaf::result<VIGEM_ERROR> w_gamepad_virtual::init() noexcept {\n  std::shared_lock _lock(this->_bus->mutex);\n\n  if (this->_bus->driver_handle == nullptr) {\n    return W_FAILURE(VIGEM_ERROR::VIGEM_ERROR_BUS_INVALID_HANDLE,\n                     \"invalid ViGem bus while creating ViGem target controller\");\n  }\n\n  // allocate handle to identify new pad\n  this->_target = vigem_target_x360_alloc();\n  if (this->_target == nullptr) {\n    return W_FAILURE(VIGEM_ERROR::VIGEM_ERROR_TARGET_NOT_PLUGGED_IN,\n                     \"could not allocate memory while creating ViGem target controller\");\n  }\n\n  // add client to the bus, this equals a plug-in event\n  auto _ret = vigem_target_add(this->_bus->driver_handle, this->_target);\n  if (_ret == VIGEM_ERROR::VIGEM_ERROR_NONE) {\n    return _ret;\n  }\n  return W_FAILURE(_ret, \"could not add ViGem target controller to the bus\");\n}\n\nboost::leaf::result<VIGEM_ERROR> w_gamepad_virtual::clear_state() noexcept {\n  std::shared_lock _lock(this->_bus->mutex);\n\n  // xinput state\n  XUSB_REPORT _state = {0};\n  // update x360 gamepad\n  return vigem_target_x360_update(this->_bus->driver_handle, this->_target, _state);\n}\n\nboost::leaf::result<VIGEM_ERROR>\nw_gamepad_virtual::send_input(_In_ XINPUT_STATE &p_xinput) noexcept {\n  std::shared_lock _lock(this->_bus->mutex);\n\n  // update x360 gamepad\n  const auto _ret = vigem_target_x360_update(this->_bus->driver_handle, this->_target,\n      *reinterpret_cast<XUSB_REPORT *>(&p_xinput.Gamepad));\n  return _ret;\n}\n\nvoid w_gamepad_virtual::_release() noexcept {\n  if (this->_bus == nullptr)\n    return;\n\n  std::shared_lock _lock(this->_bus->mutex);\n\n  if (this->_target != nullptr) {\n    if (this->_bus->driver_handle != nullptr) {\n      vigem_target_remove(this->_bus->driver_handle, this->_target);\n    }\n    vigem_target_free(this->_target);\n  }\n}\n\n#endif // #if defined(WOLF_SYSTEM_VIRTUAL_GAMEPAD) && !defined(EMSCRIPTEN)\n\n\n\n"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_virtual.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n#if defined(WOLF_SYSTEM_GAMEPAD_VIRTUAL) && !defined(EMSCRIPTEN)\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#include <ViGEm/Client.h>\n#include <Xinput.h>\n#include \"w_gamepad_virtual_bus.hpp\"\n#include <DISABLE_ANALYSIS_END>\n\nnamespace wolf::system::gamepad {\nstruct w_gamepad_virtual {\npublic:\n  // default constructor\n W_API w_gamepad_virtual(_In_ std::shared_ptr<w_gamepad_virtual_bus> p_vigem_bus) noexcept;\n\n  // destructor\n  W_API virtual ~w_gamepad_virtual() noexcept;\n\n  // move constructor\n  W_API w_gamepad_virtual(_Inout_ w_gamepad_virtual &&p_other) noexcept;\n\n  // move assignment operator.\n  W_API w_gamepad_virtual &\n  operator=(_Inout_ w_gamepad_virtual &&p_other) noexcept;\n\n  /**\n   * initialize the gamepad\n   * @returns VIGEM_ERROR\n   */\n  W_API boost::leaf::result<VIGEM_ERROR> init() noexcept;\n\n  /**\n   * clear the state of this gamepad\n   * @returns VIGEM_ERROR\n   */\n  W_API boost::leaf::result<VIGEM_ERROR> clear_state() noexcept;\n\n  /**\n   * send an input to this gamepad\n   * @param p_xinput an x input of gamepad\n   * @returns VIGEM_ERROR\n   */\n  W_API boost::leaf::result<VIGEM_ERROR>\n  send_input(_In_ XINPUT_STATE &p_xinput) noexcept;\n\nprivate:\n  // copy constructor.\n  w_gamepad_virtual(const w_gamepad_virtual &) = delete;\n  // copy assignment operator.\n  w_gamepad_virtual &operator=(const w_gamepad_virtual &) = delete;\n\n  void _move(_Inout_ w_gamepad_virtual &&p_other) noexcept;\n  void _release() noexcept;\n\n  std::shared_ptr<w_gamepad_virtual_bus> _bus;\n  PVIGEM_TARGET _target = nullptr;\n  VIGEM_ERROR _last_error = VIGEM_ERROR::VIGEM_ERROR_NONE;\n};\n} // namespace wolf::system::gamepad\n\n#endif // defined(WOLF_SYSTEM_VIRTUAL_GAMEPAD) && !defined(EMSCRIPTEN)\n"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_virtual_bus.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n#if defined(WOLF_SYSTEM_GAMEPAD_VIRTUAL) && !defined(EMSCRIPTEN)\n\n#pragma once\n\n#include \"w_gamepad_virtual.hpp\"\n#include <shared_mutex>\n\nnamespace wolf::system::gamepad {\nstruct w_gamepad_virtual_bus {\n  std::shared_mutex mutex = {};\n  PVIGEM_CLIENT driver_handle = nullptr;\n};\n}  // namespace wolf::system::gamepad\n\n#endif // defined(WOLF_SYSTEM_VIRTUAL_GAMEPAD) && !defined(EMSCRIPTEN)\n"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_virtual_pool.cpp",
    "content": "#if defined(WOLF_SYSTEM_GAMEPAD_VIRTUAL) && !defined(EMSCRIPTEN)\n\n#include \"w_gamepad_virtual_pool.hpp\"\n#include <shared_mutex>\n\nusing w_gamepad_virtual = wolf::system::gamepad::w_gamepad_virtual;\nusing w_gamepad_virtual_pool = wolf::system::gamepad::w_gamepad_virtual_pool;\nusing w_gamepad_virtual_bus = wolf::system::gamepad::w_gamepad_virtual_bus;\n\nstatic auto s_bus = std::make_shared<w_gamepad_virtual_bus>();\n\nboost::leaf::result<VIGEM_ERROR> w_gamepad_virtual_pool::init() noexcept {\n  std::unique_lock lock(s_bus->mutex);\n\n  // check for driver handle memory\n  if (s_bus->driver_handle == nullptr) {\n    // allocate memory for bus driver\n    s_bus->driver_handle = vigem_alloc();\n    if (s_bus->driver_handle == nullptr) {\n      return W_FAILURE(std::errc::not_enough_memory, \"could not allocate memory for ViGem client\");\n    }\n  }\n\n  // connect to vigem\n  const auto _ret = vigem_connect(s_bus->driver_handle);\n  if (_ret != VIGEM_ERROR_NONE) {\n    // release it\n    fini();\n    return _ret;\n  }\n\n  return _ret;\n}\n\nboost::leaf::result<w_gamepad_virtual> w_gamepad_virtual_pool::add() noexcept {\n  auto _gamepad = w_gamepad_virtual(s_bus);\n  BOOST_LEAF_AUTO(init_res, _gamepad.init());\n  return _gamepad;\n}\n\nvoid w_gamepad_virtual_pool::fini() noexcept {\n  std::unique_lock lock(s_bus->mutex);\n\n  if (s_bus->driver_handle) {\n    vigem_disconnect(s_bus->driver_handle);\n    vigem_free(s_bus->driver_handle);\n    s_bus->driver_handle = nullptr;\n  }\n}\n\nstd::string w_gamepad_virtual_pool::vigem_error_to_string(\n    _In_ const VIGEM_ERROR p_error) noexcept {\n  switch (p_error) {\n  default:\n    // API succeeded\n    return \"VIGEM_ERROR_NONE\";\n  case VIGEM_ERROR::VIGEM_ERROR_BUS_NOT_FOUND:\n    return \"VIGEM_ERROR_BUS_NOT_FOUND: a compatible bus driver wasn't found\";\n  case VIGEM_ERROR::VIGEM_ERROR_NO_FREE_SLOT:\n    return \"VIGEM_ERROR_NO_FREE_SLOT: all device slots are occupied, no new \"\n           \"device can be spawned\";\n  case VIGEM_ERROR::VIGEM_ERROR_INVALID_TARGET:\n    return \"VIGEM_ERROR_INVALID_TARGET: invalid target\";\n  case VIGEM_ERROR::VIGEM_ERROR_REMOVAL_FAILED:\n    return \"VIGEM_ERROR_REMOVAL_FAILED: could not remove\";\n  case VIGEM_ERROR::VIGEM_ERROR_ALREADY_CONNECTED:\n    return \"VIGEM_ERROR_ALREADY_CONNECTED: an attempt has been made to plug in \"\n           \"an already connected device\";\n  case VIGEM_ERROR::VIGEM_ERROR_TARGET_UNINITIALIZED:\n    return \"VIGEM_ERROR_TARGET_UNINITIALIZED: the target device is not \"\n           \"initialized\";\n  case VIGEM_ERROR::VIGEM_ERROR_TARGET_NOT_PLUGGED_IN:\n    return \"VIGEM_ERROR_TARGET_NOT_PLUGGED_IN: the target device is not \"\n           \"plugged in\";\n  case VIGEM_ERROR::VIGEM_ERROR_BUS_VERSION_MISMATCH:\n    return \"VIGEM_ERROR_TARGET_NOT_PLUGGED_IN: it's been attempted to \"\n           \"communicate with an incompatible driver version\";\n  case VIGEM_ERROR::VIGEM_ERROR_BUS_ACCESS_FAILED:\n    return \"VIGEM_ERROR_BUS_ACCESS_FAILED: bus driver found but failed \"\n           \"to open \"\n           \"a handle.\";\n  case VIGEM_ERROR::VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED:\n    return \"VIGEM_ERROR_CALLBACK_ALREADY_REGISTERED: bus driver found but \"\n           \"failed to open a handle.\";\n  case VIGEM_ERROR::VIGEM_ERROR_CALLBACK_NOT_FOUND:\n    return \"VIGEM_ERROR_CALLBACK_NOT_FOUND: bus driver found but failed to \"\n           \"open a handle.\";\n  case VIGEM_ERROR::VIGEM_ERROR_BUS_ALREADY_CONNECTED:\n    return \"VIGEM_ERROR_BUS_ALREADY_CONNECTED: bus driver found but failed to \"\n           \"open a handle.\";\n  case VIGEM_ERROR::VIGEM_ERROR_BUS_INVALID_HANDLE:\n    return \"VIGEM_ERROR_BUS_INVALID_HANDLE: bus driver found but \"\n           \"failed to open \"\n           \"a handle.\";\n  case VIGEM_ERROR::VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE:\n    return \"VIGEM_ERROR_XUSB_USERINDEX_OUT_OF_RANGE: bus driver found but \"\n           \"failed to open a handle.\";\n  case VIGEM_ERROR::VIGEM_ERROR_INVALID_PARAMETER:\n    return \"VIGEM_ERROR_INVALID_PARAMETER: bus driver found but failed to open \"\n           \"a handle.\";\n  case VIGEM_ERROR::VIGEM_ERROR_NOT_SUPPORTED:\n    return \"VIGEM_ERROR_NOT_SUPPORTED: the API is not supported by the driver\";\n  case VIGEM_ERROR::VIGEM_ERROR_WINAPI:\n    return \"VIGEM_ERROR_WINAPI: an unexpected Win32 API error occurred. Call \"\n           \"GetLastError() for details\";\n  case VIGEM_ERROR::VIGEM_ERROR_TIMED_OUT:\n    return \"VIGEM_ERROR_TIMED_OUT: the specified timeout has been reached\";\n  };\n}\n\n#endif // #if defined(WOLF_SYSTEM_VIRTUAL_GAMEPAD) && !defined(EMSCRIPTEN)\n\n\n\n"
  },
  {
    "path": "wolf/system/gamepad/w_gamepad_virtual_pool.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n#if defined(WOLF_SYSTEM_GAMEPAD_VIRTUAL) && !defined(EMSCRIPTEN)\n\n#pragma once\n\n#include \"w_gamepad_virtual.hpp\"\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system::gamepad {\nclass w_gamepad_virtual_pool {\npublic:\n  /**\n   * initialize ViGEm bus\n   * @returns VIGEM_ERROR\n   */\n  W_API static boost::leaf::result<VIGEM_ERROR> init() noexcept;\n\n  /**\n   * add a gamepad to the ViGEm bus\n   * @returns a tuple which contains index of gamepad and VIGEM_ERROR\n   */\n  W_API static boost::leaf::result<w_gamepad_virtual> add() noexcept;\n\n  /**\n   * convert a ViGEm error to string\n   * @returns a string of VIGEM_ERROR\n   */\n  W_API static std::string\n  vigem_error_to_string(_In_ const VIGEM_ERROR p_error) noexcept;\n\n  /**\n   * finitialize initialize ViGEm bus\n   * @returns a string of VIGEM_ERROR\n   */\n  W_API static void fini() noexcept;\n};\n} // namespace wolf::system::gamepad\n\n#endif // defined(WOLF_SYSTEM_VIRTUAL_GAMEPAD) && !defined(EMSCRIPTEN)\n"
  },
  {
    "path": "wolf/system/getopt.h",
    "content": "#ifndef __GETOPT_H__\n\n#pragma once\n\n/**\n * DISCLAIMER\n * This file is part of the mingw-w64 runtime package.\n *\n * The mingw-w64 runtime package and its code is distributed in the hope that it\n * will be useful but WITHOUT ANY WARRANTY.  ALL WARRANTIES, EXPRESSED OR\n * IMPLIED ARE HEREBY DISCLAIMED.  This includes but is not limited to\n * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n */\n /*\n * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>\n *\n * Permission to use, copy, modify, and distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n * Sponsored in part by the Defense Advanced Research Projects\n * Agency (DARPA) and Air Force Research Laboratory, Air Force\n * Materiel Command, USAF, under agreement number F39502-99-1-0512.\n */\n /*-\n  * Copyright (c) 2000 The NetBSD Foundation, Inc.\n  * All rights reserved.\n  *\n  * This code is derived from software contributed to The NetBSD Foundation\n  * by Dieter Baron and Thomas Klausner.\n  *\n  * Redistribution and use in source and binary forms, with or without\n  * modification, are permitted provided that the following conditions\n  * are met:\n  * 1. Redistributions of source code must retain the above copyright\n  *    notice, this list of conditions and the following disclaimer.\n  * 2. Redistributions in binary form must reproduce the above copyright\n  *    notice, this list of conditions and the following disclaimer in the\n  *    documentation and/or other materials provided with the distribution.\n  *\n  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS\n  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS\n  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n  * POSSIBILITY OF SUCH DAMAGE.\n  */\n\n#pragma warning(disable:4996)\n\n#define __GETOPT_H__\n\n  /* All the headers include this file. */\n#include <crtdefs.h>\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <windows.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define\tREPLACE_GETOPT\t\t/* use this getopt as the system getopt(3) */\n\n#ifdef REPLACE_GETOPT\n\tint\topterr = 1;\t\t/* if error message should be printed */\n\tint\toptind = 1;\t\t/* index into parent argv vector */\n\tint\toptopt = '?';\t\t/* character checked for validity */\n#undef\toptreset\t\t/* see getopt.h */\n#define\toptreset\t\t__mingw_optreset\n\tint\toptreset;\t\t/* reset getopt */\n\tchar* optarg;\t\t/* argument associated with option */\n#endif\n\n//extern int optind;\t\t/* index of first non-option in argv      */\n//extern int optopt;\t\t/* single option character, as parsed     */\n//extern int opterr;\t\t/* flag to enable built-in diagnostics... */\n//\t\t\t\t/* (user may set to zero, to suppress)    */\n//\n//extern char *optarg;\t\t/* pointer to argument of current option  */\n\n#define PRINT_ERROR\t((opterr) && (*options != ':'))\n\n#define FLAG_PERMUTE\t0x01\t/* permute non-options to the end of argv */\n#define FLAG_ALLARGS\t0x02\t/* treat non-options as args to option \"-1\" */\n#define FLAG_LONGONLY\t0x04\t/* operate as getopt_long_only */\n\n/* return values */\n#define\tBADCH\t\t(int)'?'\n#define\tBADARG\t\t((*options == ':') ? (int)':' : (int)'?')\n#define\tINORDER \t(int)1\n\n#ifndef __CYGWIN__\n#define __progname __argv[0]\n#else\n\textern char __declspec(dllimport)* __progname;\n#endif\n\n\tconstexpr char\tEMSG[] = \"\";\n\n\tstatic int getopt_internal(int, char* const*, const char*,\n\t\tconst struct option*, int*, int);\n\tstatic int parse_long_options(char* const*, const char*,\n\t\tconst struct option*, int*, int);\n\tstatic int gcd(int, int);\n\tstatic void permute_args(int, int, int, char* const*);\n\n\tstatic const char* place = EMSG; /* option letter processing */\n\n\t/* XXX: set optreset to 1 rather than these two */\n\tstatic int nonopt_start = -1; /* first non option argument (for permute) */\n\tstatic int nonopt_end = -1;   /* first option after non options (for permute) */\n\n\t/* Error messages */\n\tstatic const char recargchar[] = \"option requires an argument -- %c\";\n\tstatic const char recargstring[] = \"option requires an argument -- %s\";\n\tstatic const char ambig[] = \"ambiguous option -- %.*s\";\n\tstatic const char noarg[] = \"option doesn't take an argument -- %.*s\";\n\tstatic const char illoptchar[] = \"unknown option -- %c\";\n\tstatic const char illoptstring[] = \"unknown option -- %s\";\n\n\tstatic void\n\t\t_vwarnx(const char* fmt, va_list ap)\n\t{\n\t\t(void)fprintf(stderr, \"%s: \", __progname);\n\t\tif (fmt != NULL)\n\t\t\t(void)vfprintf(stderr, fmt, ap);\n\t\t(void)fprintf(stderr, \"\\n\");\n\t}\n\n\tstatic void\n\t\twarnx(const char* fmt, ...)\n\t{\n\t\tva_list ap;\n\t\tva_start(ap, fmt);\n\t\t_vwarnx(fmt, ap);\n\t\tva_end(ap);\n\t}\n\n\t/*\n\t * Compute the greatest common divisor of a and b.\n\t */\n\tstatic int\n\t\tgcd(int a, int b)\n\t{\n\t\tint c;\n\n\t\tc = a % b;\n\t\twhile (c != 0) {\n\t\t\ta = b;\n\t\t\tb = c;\n\t\t\tc = a % b;\n\t\t}\n\n\t\treturn (b);\n\t}\n\n\t/*\n\t * Exchange the block from nonopt_start to nonopt_end with the block\n\t * from nonopt_end to opt_end (keeping the same order of arguments\n\t * in each block).\n\t */\n\tstatic void\n\t\tpermute_args(int panonopt_start, int panonopt_end, int opt_end,\n\t\t\tchar* const* nargv)\n\t{\n\t\tint cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;\n\t\tchar* swap;\n\n\t\t/*\n\t\t * compute lengths of blocks and number and size of cycles\n\t\t */\n\t\tnnonopts = panonopt_end - panonopt_start;\n\t\tnopts = opt_end - panonopt_end;\n\t\tncycle = gcd(nnonopts, nopts);\n\t\tcyclelen = (opt_end - panonopt_start) / ncycle;\n\n\t\tfor (i = 0; i < ncycle; i++) {\n\t\t\tcstart = panonopt_end + i;\n\t\t\tpos = cstart;\n\t\t\tfor (j = 0; j < cyclelen; j++) {\n\t\t\t\tif (pos >= panonopt_end)\n\t\t\t\t\tpos -= nnonopts;\n\t\t\t\telse\n\t\t\t\t\tpos += nopts;\n\t\t\t\tswap = nargv[pos];\n\t\t\t\t/* LINTED const cast */\n\t\t\t\t((char**)nargv)[pos] = nargv[cstart];\n\t\t\t\t/* LINTED const cast */\n\t\t\t\t((char**)nargv)[cstart] = swap;\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef REPLACE_GETOPT\n\t/*\n\t * getopt --\n\t *\tParse argc/argv argument vector.\n\t *\n\t * [eventually this will replace the BSD getopt]\n\t */\n\tint\n\t\tgetopt(int nargc, char* const* nargv, const char* options)\n\t{\n\n\t\t/*\n\t\t * We don't pass FLAG_PERMUTE to getopt_internal() since\n\t\t * the BSD getopt(3) (unlike GNU) has never done this.\n\t\t *\n\t\t * Furthermore, since many privileged programs call getopt()\n\t\t * before dropping privileges it makes sense to keep things\n\t\t * as simple (and bug-free) as possible.\n\t\t */\n\t\treturn (getopt_internal(nargc, nargv, options, NULL, NULL, 0));\n\t}\n#endif /* REPLACE_GETOPT */\n\n\t//extern int getopt(int nargc, char * const *nargv, const char *options);\n\n#ifdef _BSD_SOURCE\n/*\n * BSD adds the non-standard `optreset' feature, for reinitialisation\n * of `getopt' parsing.  We support this feature, for applications which\n * proclaim their BSD heritage, before including this header; however,\n * to maintain portability, developers are advised to avoid it.\n */\n# define optreset  __mingw_optreset\n\textern int optreset;\n#endif\n#ifdef __cplusplus\n}\n#endif\n/*\n * POSIX requires the `getopt' API to be specified in `unistd.h';\n * thus, `unistd.h' includes this header.  However, we do not want\n * to expose the `getopt_long' or `getopt_long_only' APIs, when\n * included in this manner.  Thus, close the standard __GETOPT_H__\n * declarations block, and open an additional __GETOPT_LONG_H__\n * specific block, only when *not* __UNISTD_H_SOURCED__, in which\n * to declare the extended API.\n */\n#endif /* !defined(__GETOPT_H__) */\n\n#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)\n#define __GETOPT_LONG_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstruct option /* specification for a long form option...\t*/\n{\n                const char *name; /* option name, without leading hyphens */\n                int has_arg;      /* does it take an argument?\t\t*/\n                int *flag;        /* where to save its status, or NULL\t*/\n                int val;          /* its associated status value\t\t*/\n};\n\nenum /* permitted values for its `has_arg' field...\t*/\n{\n  no_argument = 0,   /* option never takes an argument\t*/\n  required_argument, /* option always requires an argument\t*/\n  optional_argument  /* option may take an argument\t\t*/\n};\n\n/*\n * parse_long_options --\n *\tParse long options in argc/argv argument vector.\n * Returns -1 if short_too is set and the option does not match long_options.\n */\nstatic int parse_long_options(char *const *nargv, const char *options,\n                              const struct option *long_options, int *idx, int short_too) {\n                char *current_argv, *has_equal;\n                size_t current_argv_len;\n                int i, ambiguous, match;\n\n#define IDENTICAL_INTERPRETATION(_x, _y)                       \\\n  (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \\\n   long_options[(_x)].flag == long_options[(_y)].flag &&       \\\n   long_options[(_x)].val == long_options[(_y)].val)\n\n                current_argv = (char *)place;\n                match = -1;\n                ambiguous = 0;\n\n                optind++;\n\n                if ((has_equal = strchr(current_argv, '=')) != NULL) {\n                        /* argument found (--option=arg) */\n                        current_argv_len = has_equal - current_argv;\n                        has_equal++;\n                } else\n                        current_argv_len = strlen(current_argv);\n\n                for (i = 0; long_options[i].name; i++) {\n                        /* find matching long option */\n                        if (strncmp(current_argv, long_options[i].name, current_argv_len))\n                                continue;\n\n                        if (strlen(long_options[i].name) == current_argv_len) {\n                                /* exact match */\n                                match = i;\n                                ambiguous = 0;\n                                break;\n                        }\n                        /*\n                         * If this is a known short option, don't allow\n                         * a partial match of a single character.\n                         */\n                        if (short_too && current_argv_len == 1)\n                                continue;\n\n                        if (match == -1) /* partial match */\n                                match = i;\n                        else if (!IDENTICAL_INTERPRETATION(i, match))\n                                ambiguous = 1;\n                }\n                if (ambiguous) {\n                        /* ambiguous abbreviation */\n                        if (PRINT_ERROR)\n                                warnx(ambig, (int)current_argv_len, current_argv);\n                        optopt = 0;\n                        return (BADCH);\n                }\n                if (match != -1) { /* option found */\n                        if (long_options[match].has_arg == no_argument && has_equal) {\n                                if (PRINT_ERROR)\n                                        warnx(noarg, (int)current_argv_len, current_argv);\n                                /*\n                                 * XXX: GNU sets optopt to val regardless of\n                                 * flag\n                                 */\n                                if (long_options[match].flag == NULL)\n                                        optopt = long_options[match].val;\n                                else\n                                        optopt = 0;\n                                return (BADARG);\n                        }\n                        if (long_options[match].has_arg == required_argument ||\n                            long_options[match].has_arg == optional_argument) {\n                                if (has_equal)\n                                        optarg = has_equal;\n                                else if (long_options[match].has_arg == required_argument) {\n                                        /*\n                                         * optional argument doesn't use next\n                                         * nargv\n                                         */\n                                        optarg = nargv[optind++];\n                                }\n                        }\n                        if ((long_options[match].has_arg == required_argument) &&\n                            (optarg == NULL)) {\n                                /*\n                                 * Missing argument; leading ':' indicates no\n                                 * error should be generated.\n                                 */\n                                if (PRINT_ERROR)\n                                        warnx(recargstring, current_argv);\n                                /*\n                                 * XXX: GNU sets optopt to val regardless of\n                                 * flag\n                                 */\n                                if (long_options[match].flag == NULL)\n                                        optopt = long_options[match].val;\n                                else\n                                        optopt = 0;\n                                --optind;\n                                return (BADARG);\n                        }\n                } else { /* unknown option */\n                        if (short_too) {\n                                --optind;\n                                return (-1);\n                        }\n                        if (PRINT_ERROR)\n                                warnx(illoptstring, current_argv);\n                        optopt = 0;\n                        return (BADCH);\n                }\n                if (idx)\n                        *idx = match;\n                if (long_options[match].flag) {\n                        *long_options[match].flag = long_options[match].val;\n                        return (0);\n                } else\n                        return (long_options[match].val);\n#undef IDENTICAL_INTERPRETATION\n}\n\n/*\n * getopt_internal --\n *\tParse argc/argv argument vector.  Called by user level routines.\n */\nstatic int getopt_internal(int nargc, char *const *nargv, const char *options,\n                           const struct option *long_options, int *idx, int flags) {\n                char *oli; /* option letter list index */\n                int optchar, short_too;\n                static int posixly_correct = -1;\n\n                if (options == NULL)\n                        return (-1);\n\n                /*\n                 * XXX Some GNU programs (like cvs) set optind to 0 instead of\n                 * XXX using optreset.  Work around this braindamage.\n                 */\n                if (optind == 0)\n                        optind = optreset = 1;\n\n                /*\n                 * Disable GNU extensions if POSIXLY_CORRECT is set or options\n                 * string begins with a '+'.\n                 *\n                 * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or\n                 *                 optreset != 0 for GNU compatibility.\n                 */\n                if (posixly_correct == -1 || optreset != 0)\n                        posixly_correct = (getenv(\"POSIXLY_CORRECT\") != NULL);\n                if (*options == '-')\n                        flags |= FLAG_ALLARGS;\n                else if (posixly_correct || *options == '+')\n                        flags &= ~FLAG_PERMUTE;\n                if (*options == '+' || *options == '-')\n                        options++;\n\n                optarg = NULL;\n                if (optreset)\n                        nonopt_start = nonopt_end = -1;\nstart:\n                if (optreset || !*place) { /* update scanning pointer */\n                        optreset = 0;\n                        if (optind >= nargc) { /* end of argument vector */\n                                place = EMSG;\n                                if (nonopt_end != -1) {\n                                        /* do permutation, if we have to */\n                                        permute_args(nonopt_start, nonopt_end, optind, nargv);\n                                        optind -= nonopt_end - nonopt_start;\n                                } else if (nonopt_start != -1) {\n                                        /*\n                                         * If we skipped non-options, set optind\n                                         * to the first of them.\n                                         */\n                                        optind = nonopt_start;\n                                }\n                                nonopt_start = nonopt_end = -1;\n                                return (-1);\n                        }\n                        if (*(place = nargv[optind]) != '-' ||\n                            (place[1] == '\\0' && strchr(options, '-') == NULL)) {\n                                place = EMSG; /* found non-option */\n                                if (flags & FLAG_ALLARGS) {\n                                        /*\n                                         * GNU extension:\n                                         * return non-option as argument to\n                                         * option 1\n                                         */\n                                        optarg = nargv[optind++];\n                                        return (INORDER);\n                                }\n                                if (!(flags & FLAG_PERMUTE)) {\n                                        /*\n                                         * If no permutation wanted, stop\n                                         * parsing at first non-option.\n                                         */\n                                        return (-1);\n                                }\n                                /* do permutation */\n                                if (nonopt_start == -1)\n                                        nonopt_start = optind;\n                                else if (nonopt_end != -1) {\n                                        permute_args(nonopt_start, nonopt_end, optind, nargv);\n                                        nonopt_start = optind - (nonopt_end - nonopt_start);\n                                        nonopt_end = -1;\n                                }\n                                optind++;\n                                /* process next argument */\n                                goto start;\n                        }\n                        if (nonopt_start != -1 && nonopt_end == -1)\n                                nonopt_end = optind;\n\n                        /*\n                         * If we have \"-\" do nothing, if \"--\" we are done.\n                         */\n                        if (place[1] != '\\0' && *++place == '-' && place[1] == '\\0') {\n                                optind++;\n                                place = EMSG;\n                                /*\n                                 * We found an option (--), so if we skipped\n                                 * non-options, we have to permute.\n                                 */\n                                if (nonopt_end != -1) {\n                                        permute_args(nonopt_start, nonopt_end, optind, nargv);\n                                        optind -= nonopt_end - nonopt_start;\n                                }\n                                nonopt_start = nonopt_end = -1;\n                                return (-1);\n                        }\n                }\n\n                /*\n                 * Check long options if:\n                 *  1) we were passed some\n                 *  2) the arg is not just \"-\"\n                 *  3) either the arg starts with -- we are getopt_long_only()\n                 */\n                if (long_options != NULL && place != nargv[optind] &&\n                    (*place == '-' || (flags & FLAG_LONGONLY))) {\n                        short_too = 0;\n                        if (*place == '-')\n                                place++; /* --foo long option */\n                        else if (*place != ':' && strchr(options, *place) != NULL)\n                                short_too = 1; /* could be short option too */\n\n                        optchar = parse_long_options(nargv, options, long_options, idx, short_too);\n                        if (optchar != -1) {\n                                place = EMSG;\n                                return (optchar);\n                        }\n                }\n\n                if ((optchar = (int)*place++) == (int)':' ||\n                    (optchar == (int)'-' && *place != '\\0') ||\n                    (oli = (char *)strchr(options, optchar)) == NULL) {\n                        /*\n                         * If the user specified \"-\" and  '-' isn't listed in\n                         * options, return -1 (non-option) as per POSIX.\n                         * Otherwise, it is an unknown option character (or\n                         * ':').\n                         */\n                        if (optchar == (int)'-' && *place == '\\0')\n                                return (-1);\n                        if (!*place)\n                                ++optind;\n                        if (PRINT_ERROR)\n                                warnx(illoptchar, optchar);\n                        optopt = optchar;\n                        return (BADCH);\n                }\n                if (long_options != NULL && optchar == 'W' && oli[1] == ';') {\n                        /* -W long-option */\n                        if (*place) /* no space */\n                                /* NOTHING */;\n                        else if (++optind >= nargc) { /* no arg */\n                                place = EMSG;\n                                if (PRINT_ERROR)\n                                        warnx(recargchar, optchar);\n                                optopt = optchar;\n                                return (BADARG);\n                        } else /* white space */\n                                place = nargv[optind];\n                        optchar = parse_long_options(nargv, options, long_options, idx, 0);\n                        place = EMSG;\n                        return (optchar);\n                }\n                if (*++oli != ':') { /* doesn't take argument */\n                        if (!*place)\n                                ++optind;\n                } else { /* takes (optional) argument */\n                        optarg = NULL;\n                        if (*place) /* no white space */\n                                optarg = (char *)place;\n                        else if (oli[1] != ':') {        /* arg not optional */\n                                if (++optind >= nargc) { /* no arg */\n                                        place = EMSG;\n                                        if (PRINT_ERROR)\n                                          warnx(recargchar, optchar);\n                                        optopt = optchar;\n                                        return (BADARG);\n                                } else\n                                        optarg = nargv[optind];\n                        }\n                        place = EMSG;\n                        ++optind;\n                }\n                /* dump back option letter */\n                return (optchar);\n}\n\n/*\n * getopt_long --\n *\tParse argc/argv argument vector.\n */\nint getopt_long(int nargc, char *const *nargv, const char *options,\n                const struct option *long_options, int *idx) {\n                return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE));\n}\n\n/*\n * getopt_long_only --\n *\tParse argc/argv argument vector.\n */\nint getopt_long_only(int nargc, char *const *nargv, const char *options,\n                     const struct option *long_options, int *idx) {\n                return (getopt_internal(nargc, nargv, options, long_options, idx,\n                                        FLAG_PERMUTE | FLAG_LONGONLY));\n}\n\n// extern int getopt_long(int nargc, char * const *nargv, const char *options,\n//     const struct option *long_options, int *idx);\n// extern int getopt_long_only(int nargc, char * const *nargv, const char\n// *options,\n//     const struct option *long_options, int *idx);\n/*\n * Previous MinGW implementation had...\n */\n#ifndef HAVE_DECL_GETOPT\n/*\n * ...for the long form API only; keep this for compatibility.\n */\n#define HAVE_DECL_GETOPT 1\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */"
  },
  {
    "path": "wolf/system/invocable.h",
    "content": "#ifndef _ANY_INVOKABLE_H_\n#define _ANY_INVOKABLE_H_\n\n#include <functional>\n#include <memory>\n#include <type_traits>\n\n// clang-format off\n/*\nnamespace std {\n  template<class Sig> class any_invocable; // never defined\n\n  template<class R, class... ArgTypes>\n  class any_invocable<R(ArgTypes...) cv ref noexcept(noex)> {\n  public:\n    using result_type = R;\n\n    // SECTION.3, construct/copy/destroy\n    any_invocable() noexcept;\n    any_invocable(nullptr_t) noexcept;\n    any_invocable(any_invocable&&) noexcept;\n    template<class F> any_invocable(F&&);\n\n    template<class T, class... Args>\n      explicit any_invocable(in_place_type_t<T>, Args&&...);\n    template<class T, class U, class... Args>\n      explicit any_invocable(in_place_type_t<T>, initializer_list<U>, Args&&...);\n\n    any_invocable& operator=(any_invocable&&) noexcept;\n    any_invocable& operator=(nullptr_t) noexcept;\n    template<class F> any_invocable& operator=(F&&);\n    template<class F> any_invocable& operator=(reference_wrapper<F>) noexcept;\n\n    ~any_invocable();\n\n    // SECTION.4, any_invocable modifiers\n    void swap(any_invocable&) noexcept;\n\n    // SECTION.5, any_invocable capacity\n    explicit operator bool() const noexcept;\n\n    // SECTION.6, any_invocable invocation\n    R operator()(ArgTypes...) cv ref noexcept(noex);\n\n    // SECTION.7, null pointer comparisons\n    friend bool operator==(const any_invocable&, nullptr_t) noexcept;\n\n    // SECTION.8, specialized algorithms\n    friend void swap(any_invocable&, any_invocable&) noexcept;\n  };\n}\n*/\n// clang-format on\n\nnamespace ofats {\n\nnamespace any_detail {\n\n//using buffer = std::aligned_storage_t<sizeof(void*) * 2, alignof(void*)>;\nstruct buffer {\n  alignas(void*) std::byte t_buff[sizeof(sizeof(void*) * 2)];\n};\n\ntemplate <class T>\ninline constexpr bool is_small_object_v =\n    sizeof(T) <= sizeof(buffer) && alignof(buffer) % alignof(T) == 0 &&\n    std::is_nothrow_move_constructible_v<T>;\n\nunion storage {\n  void* ptr_ = nullptr;\n  buffer buf_;\n};\n\nenum class action { destroy, move };\n\ntemplate <class R, class... ArgTypes>\nstruct handler_traits {\n  template <class Derived>\n  struct handler_base {\n    static void handle(action act, storage* current, storage* other = nullptr) {\n      switch (act) {\n        case (action::destroy):\n          Derived::destroy(*current);\n          break;\n        case (action::move):\n          Derived::move(*current, *other);\n          break;\n      }\n    }\n  };\n\n  template <class T>\n  struct small_handler : handler_base<small_handler<T>> {\n    template <class... Args>\n    static void create(storage& s, Args&&... args) {\n      new (static_cast<void*>(&s.buf_)) T(std::forward<Args>(args)...);\n    }\n\n    static void destroy(storage& s) noexcept {\n      T& value = *static_cast<T*>(static_cast<void*>(&s.buf_));\n      value.~T();\n    }\n\n    static void move(storage& dst, storage& src) noexcept {\n      create(dst, std::move(*static_cast<T*>(static_cast<void*>(&src.buf_))));\n      destroy(src);\n    }\n\n    static R call(const storage& s, ArgTypes... args) {\n      return std::invoke(\n          *static_cast<T*>(static_cast<void*>(&const_cast<storage&>(s).buf_)),\n          std::forward<ArgTypes>(args)...);\n    }\n  };\n\n  template <class T>\n  struct large_handler : handler_base<large_handler<T>> {\n    template <class... Args>\n    static void create(storage& s, Args&&... args) {\n      s.ptr_ = new T(std::forward<Args>(args)...);\n    }\n\n    static void destroy(storage& s) noexcept { delete static_cast<T*>(s.ptr_); }\n\n    static void move(storage& dst, storage& src) noexcept {\n      dst.ptr_ = src.ptr_;\n    }\n\n    static R call(const storage& s, ArgTypes... args) {\n      return std::invoke(*static_cast<T*>(s.ptr_),\n                         std::forward<ArgTypes>(args)...);\n    }\n  };\n\n  template <class T>\n  using handler = std::conditional_t<is_small_object_v<T>, small_handler<T>,\n                                     large_handler<T>>;\n};\n\ntemplate <class T>\nstruct is_in_place_type : std::false_type {};\n\ntemplate <class T>\nstruct is_in_place_type<std::in_place_type_t<T>> : std::true_type {};\n\ntemplate <class T>\ninline constexpr auto is_in_place_type_v = is_in_place_type<T>::value;\n\ntemplate <class R, bool is_noexcept, class... ArgTypes>\nclass any_invocable_impl {\n  template <class T>\n  using handler =\n      typename any_detail::handler_traits<R, ArgTypes...>::template handler<T>;\n\n  using storage = any_detail::storage;\n  using action = any_detail::action;\n  using handle_func = void (*)(any_detail::action, any_detail::storage*,\n                               any_detail::storage*);\n  using call_func = R (*)(const any_detail::storage&, ArgTypes...);\n\n public:\n  using result_type = R;\n\n  any_invocable_impl() noexcept = default;\n  any_invocable_impl(std::nullptr_t) noexcept {}\n  any_invocable_impl(any_invocable_impl&& rhs) noexcept {\n    if (rhs.handle_) {\n      handle_ = rhs.handle_;\n      handle_(action::move, &storage_, &rhs.storage_);\n      call_ = rhs.call_;\n      rhs.handle_ = nullptr;\n    }\n  }\n\n  any_invocable_impl& operator=(any_invocable_impl&& rhs) noexcept {\n    any_invocable_impl{std::move(rhs)}.swap(*this);\n    return *this;\n  }\n  any_invocable_impl& operator=(std::nullptr_t) noexcept {\n    destroy();\n    return *this;\n  }\n\n  ~any_invocable_impl() { destroy(); }\n\n  void swap(any_invocable_impl& rhs) noexcept {\n    if (handle_) {\n      if (rhs.handle_) {\n        storage tmp;\n        handle_(action::move, &tmp, &storage_);\n        rhs.handle_(action::move, &storage_, &rhs.storage_);\n        handle_(action::move, &rhs.storage_, &tmp);\n        std::swap(handle_, rhs.handle_);\n        std::swap(call_, rhs.call_);\n      } else {\n        rhs.swap(*this);\n      }\n    } else if (rhs.handle_) {\n      rhs.handle_(action::move, &storage_, &rhs.storage_);\n      handle_ = rhs.handle_;\n      call_ = rhs.call_;\n      rhs.handle_ = nullptr;\n    }\n  }\n\n  explicit operator bool() const noexcept { return handle_ != nullptr; }\n\n protected:\n  template <class F, class... Args>\n  void create(Args&&... args) {\n    using hdl = handler<F>;\n    hdl::create(storage_, std::forward<Args>(args)...);\n    handle_ = &hdl::handle;\n    call_ = &hdl::call;\n  }\n\n  void destroy() noexcept {\n    if (handle_) {\n      handle_(action::destroy, &storage_, nullptr);\n      handle_ = nullptr;\n    }\n  }\n\n  R call(ArgTypes... args) const noexcept(is_noexcept) {\n    return call_(storage_, std::forward<ArgTypes>(args)...);\n  }\n\n  friend bool operator==(const any_invocable_impl& f, std::nullptr_t) noexcept {\n    return !f;\n  }\n  friend bool operator==(std::nullptr_t, const any_invocable_impl& f) noexcept {\n    return !f;\n  }\n  friend bool operator!=(const any_invocable_impl& f, std::nullptr_t) noexcept {\n    return static_cast<bool>(f);\n  }\n  friend bool operator!=(std::nullptr_t, const any_invocable_impl& f) noexcept {\n    return static_cast<bool>(f);\n  }\n\n  friend void swap(any_invocable_impl& lhs, any_invocable_impl& rhs) noexcept {\n    lhs.swap(rhs);\n  }\n\n private:\n  storage storage_;\n  handle_func handle_ = nullptr;\n  call_func call_;\n};\n\ntemplate <class T>\nusing remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;\n\ntemplate <class AI, class F, bool noex, class R, class FCall, class... ArgTypes>\nusing can_convert = std::conjunction<\n    std::negation<std::is_same<remove_cvref_t<F>, AI>>,\n    std::negation<any_detail::is_in_place_type<remove_cvref_t<F>>>,\n    std::is_invocable_r<R, FCall, ArgTypes...>,\n    std::bool_constant<(!noex ||\n                        std::is_nothrow_invocable_r_v<R, FCall, ArgTypes...>)>,\n    std::is_constructible<std::decay_t<F>, F>>;\n\n}  // namespace any_detail\n\ntemplate <class Signature>\nclass any_invocable;\n\n#define __OFATS_ANY_INVOCABLE(cv, ref, noex, inv_quals)                        \\\n  template <class R, class... ArgTypes>                                        \\\n  class any_invocable<R(ArgTypes...) cv ref noexcept(noex)> final              \\\n      : public any_detail::any_invocable_impl<R, noex, ArgTypes...> {          \\\n    using base_type = any_detail::any_invocable_impl<R, noex, ArgTypes...>;    \\\n                                                                               \\\n   public:                                                                     \\\n    using base_type::base_type;                                                \\\n                                                                               \\\n    template <                                                                 \\\n        class F,                                                               \\\n        class = std::enable_if_t<any_detail::can_convert<                      \\\n            any_invocable, F, noex, R, F inv_quals, ArgTypes...>::value>>      \\\n    any_invocable(F&& f) {                                                     \\\n      base_type::template create<std::decay_t<F>>(std::forward<F>(f));         \\\n    }                                                                          \\\n                                                                               \\\n    template <class T, class... Args, class VT = std::decay_t<T>,              \\\n              class = std::enable_if_t<                                        \\\n                  std::is_move_constructible_v<VT> &&                          \\\n                  std::is_constructible_v<VT, Args...> &&                      \\\n                  std::is_invocable_r_v<R, VT inv_quals, ArgTypes...> &&       \\\n                  (!noex || std::is_nothrow_invocable_r_v<R, VT inv_quals,     \\\n                                                          ArgTypes...>)>>      \\\n    explicit any_invocable(std::in_place_type_t<T>, Args&&... args) {          \\\n      base_type::template create<VT>(std::forward<Args>(args)...);             \\\n    }                                                                          \\\n                                                                               \\\n    template <                                                                 \\\n        class T, class U, class... Args, class VT = std::decay_t<T>,           \\\n        class = std::enable_if_t<                                              \\\n            std::is_move_constructible_v<VT> &&                                \\\n            std::is_constructible_v<VT, std::initializer_list<U>&, Args...> && \\\n            std::is_invocable_r_v<R, VT inv_quals, ArgTypes...> &&             \\\n            (!noex ||                                                          \\\n             std::is_nothrow_invocable_r_v<R, VT inv_quals, ArgTypes...>)>>    \\\n    explicit any_invocable(std::in_place_type_t<T>,                            \\\n                           std::initializer_list<U> il, Args&&... args) {      \\\n      base_type::template create<VT>(il, std::forward<Args>(args)...);         \\\n    }                                                                          \\\n                                                                               \\\n    template <class F, class FDec = std::decay_t<F>>                           \\\n    std::enable_if_t<!std::is_same_v<FDec, any_invocable> &&                   \\\n                         std::is_move_constructible_v<FDec>,                   \\\n                     any_invocable&>                                           \\\n    operator=(F&& f) {                                                         \\\n      any_invocable{std::forward<F>(f)}.swap(*this);                           \\\n      return *this;                                                            \\\n    }                                                                          \\\n    template <class F>                                                         \\\n    any_invocable& operator=(std::reference_wrapper<F> f) {                    \\\n      any_invocable{f}.swap(*this);                                            \\\n      return *this;                                                            \\\n    }                                                                          \\\n                                                                               \\\n    R operator()(ArgTypes... args) cv ref noexcept(noex) {                     \\\n      return base_type::call(std::forward<ArgTypes>(args)...);                 \\\n    }                                                                          \\\n  }\n\n// cv -> {`empty`, const}\n// ref -> {`empty`, &, &&}\n// noex -> {true, false}\n// inv_quals -> (is_empty(ref) ? & : ref)\n__OFATS_ANY_INVOCABLE(, , false, &);               // 000\n__OFATS_ANY_INVOCABLE(, , true, &);                // 001\n__OFATS_ANY_INVOCABLE(, &, false, &);              // 010\n__OFATS_ANY_INVOCABLE(, &, true, &);               // 011\n__OFATS_ANY_INVOCABLE(, &&, false, &&);            // 020\n__OFATS_ANY_INVOCABLE(, &&, true, &&);             // 021\n__OFATS_ANY_INVOCABLE(const, , false, const&);     // 100\n__OFATS_ANY_INVOCABLE(const, , true, const&);      // 101\n__OFATS_ANY_INVOCABLE(const, &, false, const&);    // 110\n__OFATS_ANY_INVOCABLE(const, &, true, const&);     // 111\n__OFATS_ANY_INVOCABLE(const, &&, false, const&&);  // 120\n__OFATS_ANY_INVOCABLE(const, &&, true, const&&);   // 121\n\n#undef __OFATS_ANY_INVOCABLE\n\n}  // namespace ofats\n\n#endif  // _ANY_INVOKABLE_H_\n"
  },
  {
    "path": "wolf/system/log/w_log.cpp",
    "content": "#ifdef WOLF_SYSTEM_LOG\n\n#include \"w_log.hpp\"\n\nusing w_log = wolf::system::log::w_log;\nusing w_log_config = wolf::system::log::w_log_config;\n\nw_log::w_log(_In_ w_log_config &&p_config) noexcept\n    : _config(std::move(p_config)) {}\n\nw_log::~w_log() noexcept {\n  try {\n    flush();\n  } catch (...) {\n  }\n}\n\nvoid w_log::_move(_Inout_ w_log &&p_other) noexcept {\n  if (this == &p_other) {\n    return;\n  }\n\n  this->_config = std::move(p_other._config);\n  this->_logger = std::move(p_other._logger);\n  this->_async_file_logger = std::move(p_other._async_file_logger);\n}\n\nboost::leaf::result<int> w_log::init() {\n  // first create a directory for log\n  const auto _parent_path = this->_config.path.parent_path();\n  const auto _is_dir = std::filesystem::is_directory(_parent_path);\n  if (!_is_dir) {\n    // try to create a directory for it\n    try {\n      const auto _dir_created = std::filesystem::create_directory(_parent_path);\n      if (!_dir_created) {\n        return W_FAILURE(std::errc::invalid_argument,\n                         \"could not create log directory path\");\n      }\n    } catch (...) {\n      return W_FAILURE(std::errc::operation_canceled,\n                       \"could not create log directory path because\");\n    }\n  }\n\n  // create sinks\n  std::vector<spdlog::sink_ptr> _sinks;\n  if (this->_config.type & w_log_sink::CONSOLE) {\n    if (this->_config.multi_threaded) {\n      _sinks.push_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());\n    } else {\n      _sinks.push_back(std::make_shared<spdlog::sinks::stdout_color_sink_st>());\n    }\n  }\n\n#if defined(_MSC_VER)\n  if (this->_config.type & w_log_sink::VISUAL_STUDIO) {\n    if (this->_config.multi_threaded) {\n      _sinks.push_back(std::make_shared<spdlog::sinks::msvc_sink_mt>());\n    } else {\n      _sinks.push_back(std::make_shared<spdlog::sinks::msvc_sink_st>());\n    }\n  }\n#endif\n\n  const auto _level = this->_config.level;\n  const auto _flush_level = this->_config.flush_level;\n\n  const auto _filename = this->_config.path.filename().string();\n  const auto _path = this->_config.path.string();\n\n  if (this->_config.type & w_log_sink::ASYNC_FILE) {\n    // async file sink\n    this->_async_file_logger =\n        spdlog::create_async_nb<spdlog::sinks::rotating_file_sink_mt>(\n            _filename, _path, this->_config.max_file_size_in_mb,\n            this->_config.max_files, this->_config.rotate_on_open);\n    if (this->_async_file_logger == nullptr) {\n      return W_FAILURE(std::errc::invalid_argument,\n                       \"could not allocate memory for async file logger\");\n    }\n\n    this->_async_file_logger->set_level(_level);\n    this->_async_file_logger->flush_on(_flush_level);\n  } else if (this->_config.type & w_log_sink::ASYNC_DAILY_FILE) {\n    // async daily file sink\n    this->_async_file_logger =\n        spdlog::create_async_nb<spdlog::sinks::daily_file_sink_mt>(\n            _filename, _path, this->_config.hour, this->_config.minute,\n            false,  // truncate\n            gsl::narrow_cast<uint16_t>(this->_config.max_files));\n    if (this->_async_file_logger == nullptr) {\n      return W_FAILURE(std::errc::invalid_argument,\n                       \"could not allocate memory for daily async file logger\");\n    }\n\n    this->_async_file_logger->set_level(_level);\n    this->_async_file_logger->flush_on(_flush_level);\n  }\n\n  // create logger for other sinks\n  this->_logger =\n      std::make_shared<spdlog::logger>(_filename, _sinks.begin(), _sinks.end());\n  if (this->_logger == nullptr) {\n    return W_FAILURE(std::errc::invalid_argument, \"could not create logger\");\n  }\n\n  this->_logger->set_level(_level);\n  this->_logger->flush_on(_flush_level);\n\n  return 0;\n}\n\nvoid w_log::write(_In_ const std::string_view &p_fmt) {\n  write(spdlog::level::level_enum::info, p_fmt);\n}\n\nvoid w_log::write(_In_ const spdlog::level::level_enum &p_level,\n                  _In_ const std::string_view &p_fmt) {\n  if (this->_logger != nullptr) {\n    this->_logger->log(p_level, p_fmt);\n  }\n  if (this->_async_file_logger != nullptr) {\n    this->_async_file_logger->log(p_level, p_fmt);\n  }\n}\n\nboost::leaf::result<int> w_log::flush() {\n  if (this->_logger != nullptr) {\n    this->_logger->flush();\n  }\n  if (this->_async_file_logger != nullptr) {\n    this->_async_file_logger->flush();\n  }\n  return 0;\n}\n\nw_log_config w_log::get_config() const { return this->_config; }\n\n#endif"
  },
  {
    "path": "wolf/system/log/w_log.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#ifdef WOLF_SYSTEM_LOG\n\n#include <spdlog/async.h>\n#include <spdlog/sinks/basic_file_sink.h>\n#include <spdlog/sinks/daily_file_sink.h>\n#include <spdlog/sinks/rotating_file_sink.h>\n#include <spdlog/sinks/stdout_color_sinks.h>\n\n#include <DISABLE_ANALYSIS_BEGIN>\n#include <wolf/wolf.hpp>\n\n#include \"w_log_config.hpp\"\n\n#ifdef _MSC_VER\n#include <spdlog/sinks/msvc_sink.h>\n#endif\n\n#include <DISABLE_ANALYSIS_END>\n\nnamespace wolf::system::log {\nclass w_log {\n public:\n  // constructor\n  W_API explicit w_log(w_log_config &&p_config) noexcept;\n\n  // move constructor.\n  W_API w_log(w_log &&p_other) noexcept {\n    _move(std::forward<w_log &&>(p_other));\n  }\n  // move assignment operator.\n  W_API w_log &operator=(w_log &&p_other) noexcept {\n    _move(std::forward<w_log &&>(p_other));\n    return *this;\n  }\n\n  // destructor\n  W_API virtual ~w_log() noexcept;\n\n  W_API boost::leaf::result<int> init();\n\n  W_API void write(_In_ const std::string_view &p_fmt);\n\n  W_API void write(_In_ const spdlog::level::level_enum &p_level,\n                   _In_ const std::string_view &p_fmt);\n\n#ifdef _MSC_VER\n\n  template <class... Args>\n  W_API void write(_In_ const std::string_view p_fmt, _In_ Args &&...p_args) {\n    const auto _str = std::vformat(p_fmt, std::make_format_args(p_args...));\n    write(_str);\n  }\n\n  template <class... Args>\n  W_API void write(_In_ const spdlog::level::level_enum &p_level,\n                   _In_ const std::string_view p_fmt, _In_ Args &&...p_args) {\n    const auto _str = std::vformat(p_fmt, std::make_format_args(p_args...));\n    write(p_level, _str);\n  }\n\n#else\n  template <class... Args>\n  W_API void write(_In_ const fmt::v9::format_string<Args...> p_fmt,\n                   _In_ Args &&...p_args) {\n    const auto _str =\n        fmt::v9::vformat(p_fmt, fmt::v9::make_format_args(p_args...));\n    write(_str);\n  }\n\n  template <class... Args>\n  W_API void write(_In_ const spdlog::level::level_enum &p_level,\n                   _In_ const fmt::v9::format_string<Args...> p_fmt,\n                   _In_ Args &&...p_args) {\n    const auto _str =\n        fmt::v9::vformat(p_fmt, fmt::v9::make_format_args(p_args...));\n    write(p_level, _str);\n  }\n\n#endif  // _MSC_VER\n\n  W_API boost::leaf::result<int> flush();\n\n  W_API w_log_config get_config() const;\n\n private:\n  // disable copy constructor\n  w_log(const w_log &) = delete;\n  // disable copy operator\n  w_log &operator=(const w_log &) = delete;\n\n  W_API void _move(_Inout_ w_log &&p_other) noexcept;\n\n  w_log_config &&_config = {};\n  std::shared_ptr<spdlog::logger> _logger = nullptr;\n  std::shared_ptr<spdlog::logger> _async_file_logger = nullptr;\n};\n}  // namespace wolf::system::log\n\n#endif"
  },
  {
    "path": "wolf/system/log/w_log_config.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#ifdef WOLF_SYSTEM_LOG\n\n#include <filesystem>\n#include <wolf/wolf.hpp>\n#include <spdlog/spdlog.h>\n\nnamespace wolf::system::log {\n\n// create a log with a combination of console, telemetry, visual studio and\n// (async file/async daily file) please note that you can't select both async\n// file and async daily file\nenum w_log_sink {\n  CONSOLE = (1u << 0),\n  ASYNC_FILE = (1u << 1),\n  ASYNC_DAILY_FILE = (1u << 2),\n// TELEMETRY = (1u << 3),\n#ifdef _MSC_VER\n  VISUAL_STUDIO = (1u << 4),\n#endif\n};\n\ninline w_log_sink operator|(w_log_sink p_left, w_log_sink p_right) {\n  return static_cast<w_log_sink>(static_cast<int>(p_left) |\n                                 static_cast<int>(p_right));\n}\n\nstruct w_log_config {\n  // create an async logger\n  bool async = false;\n  // enable multi-threaded\n  bool multi_threaded = false;\n  // the path of log file\n  std::filesystem::path path;\n  // the log level\n  spdlog::level::level_enum level;\n  // the flush level\n  spdlog::level::level_enum flush_level;\n  // the sinks of log\n  w_log_sink type;\n  // max file size in Mb (e.g. maximum 100 log files * with size of 100 Mb\n  // file)\n  size_t max_file_size_in_mb = 100 * 1048576;\n  // max number of files\n  size_t max_files = 10;\n  // rotate file on open\n  bool rotate_on_open = false;\n  // start creation time for daily log\n  int hour = 0;\n  // start creation time for daily log\n  int minute = 0;\n};\n} // namespace wolf::system::log\n\n#endif"
  },
  {
    "path": "wolf/system/script/w_lua.cpp",
    "content": "#include \"w_lua.hpp\"\n"
  },
  {
    "path": "wolf/system/script/w_lua.hpp",
    "content": "#pragma once\n\n#ifdef WOLF_SYSTEM_LUA\n\n#include <wolf/wolf.hpp>\n\n#define SOL_EXCEPTIONS_SAFE_PROPAGATION 1\n#define SOL_ALL_SAFETIES_ON 1\n\n#include <sol/sol.hpp>\n#include <filesystem>\n\nnamespace wolf::system::script {\nusing w_lib = sol::lib;\nclass w_lua {\n public:\n   W_API w_lua()\n      : _lua(std::make_shared<sol::state>(\n            sol::c_call<decltype(&w_lua::w_lua_panic), &w_lua::w_lua_panic>)),\n        _load_result(nullptr, -1, 0, 0, sol::load_status::syntax) {}\n\n  W_API ~w_lua() {\n     _release();\n  }\n  \n  // move constructor.\n  W_API w_lua(w_lua &&p_other) noexcept { _move(std::forward<w_lua &&>(p_other)); }\n  // move assignment operator.\n  W_API w_lua &operator=(w_lua &&p_other) noexcept {\n    _move(std::forward<w_lua &&>(p_other));\n    return *this;\n  }\n\n  /**\n   * open lua libraries\n   * @param p_libs library enum\n   */\n  template <typename... ARGS>\n  W_API void open_libraries(ARGS &&...p_libs) {\n    this->_lua->open_libraries(std::forward<ARGS>(p_libs)...);\n  }\n\n  /**\n   * load lua script from file\n   * @param p_file file path\n   */\n  W_API boost::leaf::result<void> load_file(const std::filesystem::path &p_file) {\n    _load_result = this->_lua->load_file(p_file.string());\n    if (!_load_result.valid()) {\n      sol::error err = _load_result;\n      return W_FAILURE(1, err.what());\n    }\n    return {};\n  }\n\n  /**\n   * load from buffer\n   * @param p_str string buffer\n   */\n  W_API boost::leaf::result<void> load_from_buffer(const std::string_view p_str) {\n    _load_result = this->_lua->load(p_str);\n    if (!_load_result.valid()) {\n      sol::error err = _load_result;\n      return W_FAILURE(1, err.what());\n    }\n    return {};\n  }\n\n  /**\n   * run previously loaded lua script\n   * @return result\n   */\n   template <typename... RETYPES, typename... ARGS>\n  W_API boost::leaf::result<std::tuple<RETYPES...>> run(ARGS &&...p_args) {\n    if (!_load_result.valid()) {\n      return W_FAILURE(1, \"no script currently loaded\");\n    }\n    auto result = _load_result(std::forward<ARGS>(p_args)...);\n    if (!result.valid()) {\n      sol::error err = result;\n      return W_FAILURE(1, err.what());\n    }\n\n    std::tuple<RETYPES...> value;\n    try {\n      value = result;\n    } catch (...) {\n      return W_FAILURE(1, \"can not convert arguments\");\n    }\n    return value;\n  }\n\n  /**\n   * run lua script from file\n   * @param p_file file path\n   */\n   template <typename... RETYPES>\n   W_API boost::leaf::result<std::tuple<RETYPES...>> run_file(const std::filesystem::path &p_file)\n   {\n    auto result = this->_lua->script_file(p_file.string());\n    if (!result.valid()) {\n      sol::error err = result;\n      return W_FAILURE(1, err.what());\n    }\n\n    std::tuple<RETYPES...> value;\n    try {\n      value = result;\n    } catch (...) {\n      return W_FAILURE(1, \"can not convert arguments\");\n    }\n    return value;\n  }\n\n  /**\n   * run from buffer\n   * @param p_str string buffer\n   */\n   template <typename... RETYPES>\n  W_API boost::leaf::result<std::tuple<RETYPES...>> run_from_buffer(const std::string_view& p_str) {\n    auto result = this->_lua->script(p_str);\n    if (!result.valid()) {\n      sol::error err = result;\n      return W_FAILURE(1, err.what());\n    }\n\n    std::tuple<RETYPES...> value;\n    try {\n      value = std::move(result);\n    } catch (...) {\n      return W_FAILURE(1, \"can not convert arguments\");\n    }\n    return value;\n  }\n\n  /**\n   * bind to the function\n   * @param p_lua_function lua function name\n   * @param p_args c++ function\n   */\n  template <typename... ARGS>\n  W_API boost::leaf::result<void> bind_to_function(const std::string &p_lua_function,\n                                                   ARGS &&...p_args) {\n    try {\n      this->_lua->set_function(p_lua_function, std::forward<ARGS>(p_args)...);\n    } catch (...) {\n      return W_FAILURE(1, \"can not set function\");\n    }\n    return {};\n  }\n\n  /**\n   * call lua functions\n   * @param p_name lua function name\n   * @param p_args function arguments\n   */\n   template <typename... RETYPES, typename... ARGS>\n  W_API boost::leaf::result<std::tuple<RETYPES...>> call_function(const std::string_view p_name,\n                                                                  ARGS &&...p_args) {\n    auto _ptr = this->_lua.get();\n    sol::protected_function function = (*_ptr)[p_name];\n    auto result = function(std::forward<ARGS>(p_args)...);\n    if (!result.valid()) {\n      sol::error err = result;\n      return W_FAILURE(1, err.what());\n    }\n\n    std::tuple<RETYPES...> value;\n    try {\n      value = result;\n    } catch (...) {\n      return W_FAILURE(1, \"can not convert arguments\");\n    }\n\n    return value;\n  }\n\n  /**\n   * return the lua state for custom operation\n   * @return soL state object\n   */\n  W_API std::shared_ptr<sol::state> get_state() { return this->_lua; };\n\n  /**\n   * get global variable\n   * @param p_name name of variable\n   * @param pValue value of variable\n   * @return result\n   */\n   template <typename T>\n  W_API boost::leaf::result<void> get_global_variable(const std::string_view p_name, T &p_value) {\n    try {\n      p_value = this->_lua[\"p_name\"];\n    } catch (...) {\n      return W_FAILURE(1, \"can not get global variable\");\n    }\n    return {};\n  }\n\n  /**\n   *  set global variable\n   * @param p_name name of variable\n   * @param p_value value of variable\n   * @return result\n   */\n   template <typename... ARGS>\n  W_API boost::leaf::result<void> set_global_variable(std::string_view p_name, ARGS &&...p_value) {\n    try {\n      this->_lua->set(p_name, std::forward<ARGS>(p_value)...);\n    } catch (...) {\n      return W_FAILURE(1, \"can not set global variable\");\n    }\n\n    return {};\n  }\n\n private:\n  // disable copy constructor\n  w_lua(const w_lua &) = delete;\n  // disable copy operator\n  w_lua &operator=(const w_lua &) = delete;\n\n  void _release() {\n    if (this->_lua) {\n      this->_lua->stack_clear();\n      this->_lua->collect_garbage();\n    }\n  }\n\n  void _move(w_lua &&p_other) noexcept {\n    if (this == &p_other) {\n      return;\n    }\n    this->_lua = std::move(p_other._lua);\n    this->_load_result = std::move(p_other._load_result);\n  }\n\n  inline void w_lua_panic(sol::optional<std::string> p_maybe_msg) {\n    if (p_maybe_msg) {\n      throw std::runtime_error(p_maybe_msg.value());\n    }\n  }\n\n  std::shared_ptr<sol::state> _lua;\n  sol::load_result _load_result;\n};\n}  // namespace wolf::system::script\n\n#endif\n"
  },
  {
    "path": "wolf/system/script/w_python.cpp",
    "content": "#include \"w_python.hpp\"\n\nusing w_python = wolf::system::python::w_python;\n\nw_python::w_python(const std::string_view& p_python_home_path) {\n  auto _python_home_path = std::wstring(p_python_home_path.begin(), p_python_home_path.end());\n  Py_SetPythonHome(_python_home_path.data());\n  Py_Initialize();\n}\n\nw_python::~w_python() { _release(); }\n\nvoid w_python::set_module(const std::string_view& p_module_name) {\n  this->_module_name = p_module_name;\n}\n\nvoid w_python::set_dictionary(const std::string& p_dic) { this->_dictionary_name = p_dic; }\n\nstd::string w_python::get_script() const { return this->_script; }\n\nboost::leaf::result<int> w_python::run(\n    _In_ const std::string_view& p_script,\n    std::unordered_map<std::string, std::any>& p_requested_vars) {\n  if (p_script.empty()) {\n    return W_FAILURE(std::errc::invalid_argument, \"empty python script!\");\n  }\n\n  this->_script = p_script;\n\n  try {\n    auto _main = boost::python::import(\"__main__\");\n    auto _global = boost::python::object(_main.attr(\"__dict__\"));\n    boost::python::exec(this->_script.c_str(), _global);\n\n    for (auto& var : p_requested_vars) {\n      if (var.first.empty()) {\n        continue;\n      }\n      auto _value = _global[var.first];\n\n      if (var.second.type() == typeid(bool)) {\n        var.second = gsl::narrow_cast<bool>(boost::python::extract<bool>(_value));\n      } else if (var.second.type() == typeid(int)) {\n        var.second = gsl::narrow_cast<int>(boost::python::extract<int>(_value));\n      } else if (var.second.type() == typeid(double)) {\n        var.second = gsl::narrow_cast<double>(boost::python::extract<double>(_value));\n      } else if (var.second.type() == typeid(std::string)) {\n        var.second = gsl::narrow_cast<std::string>(boost::python::extract<std::string>(_value));\n      } else {\n        return W_FAILURE(std::errc::invalid_argument, \"could not find variable: \" + var.first +\n                                                          \" in python script: \" + this->_script);\n      }\n    }\n    return 0;\n\n  } catch (boost::python::error_already_set const&) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"could not execute python code: \" + this->_script +\n                         \" because: \" + _parse_python_exception());\n  } catch (...) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"could not execute python code: \" + this->_script);\n  }\n}\n\nvoid w_python::_release() { \n    \n    Py_Finalize(); }\n\nstd::string w_python::_parse_python_exception() {\n  PyObject *type_ptr = nullptr, *value_ptr = nullptr, *traceback_ptr = nullptr;\n  // Fetch the exception info from the Python C API\n  PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);\n\n  namespace py = boost::python;\n\n  // fallback error\n  std::string ret(\"unfetchable python error\");\n\n  // If the fetch got a type pointer, parse the type into the exception string\n  if (type_ptr != nullptr) {\n    py::handle<> h_type(type_ptr);\n    py::str type_pstr(h_type);\n    // Extract the string from the boost::python object\n    py::extract<std::string> e_type_pstr(type_pstr);\n    // If a valid string extraction is available, use it\n    //  otherwise use fallback\n    if (e_type_pstr.check()) {\n      ret = e_type_pstr();\n    } else {\n      ret = \"unknown exception type\";\n    }\n  }\n\n  // Do the same for the exception value (the stringification of the exception)\n  if (value_ptr != nullptr) {\n    py::handle<> h_val(value_ptr);\n    py::str a(h_val);\n    py::extract<std::string> returned(a);\n    if (returned.check()) {\n      ret += \": \" + returned();\n    } else {\n      ret += std::string(\": unparseable python error: \");\n    }\n  }\n\n  // parse lines from the traceback using the Python traceback module\n  if (traceback_ptr != nullptr) {\n    py::handle<> h_tb(traceback_ptr);\n\n    // load the traceback module and the format_tb function\n    py::object tb(py::import(\"traceback\"));\n    py::object fmt_tb(tb.attr(\"format_tb\"));\n\n    // call format_tb to get a list of traceback strings\n    py::object tb_list(fmt_tb(h_tb));\n\n    // join the traceback strings into a single string\n    py::object tb_str(py::str(\"\\n\").join(tb_list));\n\n    // extract the string, check the extraction, and fallback in necessary\n    py::extract<std::string> returned(tb_str);\n    if (returned.check()) {\n      ret += \": \" + returned();\n    } else {\n      ret += std::string(\": unparseable python traceback\");\n    }\n  }\n  return ret;\n}\n"
  },
  {
    "path": "wolf/system/script/w_python.hpp",
    "content": "#pragma once\n\n#include <wolf.hpp>\n#include <unordered_map>\n#include <any>\n#include <Python.h>\n#include <boost/python.hpp>\n\nnamespace wolf::system::python {\n\n//std::string load_py_file(const std::filesystem::path& /* python file */);\n//\n//void run_simple_script_from_file(const std::filesystem::path& /* python file */);\n//template <typename T>\n//[[nodiscard(\"No ignore return value!\")]] T run_function_and_get_result(\n//    const std::string& /* script */, const std::string& /* function name */);\n//template <typename T>\n//[[nodiscard(\"No ignore return value!\")]] T run_function_from_file_script_and_get_result(\n//    const std::filesystem::path& /* python file */, const std::string& /* function name */);\n//template <typename... ARGS>\n//[[nodiscard(\"No ignore return value!\")]] boost::python::tuple call_function(\n//    const std::string& /* function name */, const std::string& /* script */,\n//    ARGS&&... /* arguments */);\n\n///*\n// * convert boost python tuple to standard tuple\n// */\n//template <typename... RETTYPE>\n//std::tuple<RETTYPE...> convertBPTuple2StdTuple(const boost::python::tuple&);\n\n// an wrapper over boost.python\nclass w_python {\n public:\n  // default constructor\n  W_API explicit w_python(const std::string_view& p_python_home_path);\n  // default destructor\n  W_API ~w_python();\n\n  /*\n   * set python module\n   * @param p_module_name, the module name\n   */\n  W_API void set_module(const std::string_view& p_module_name);\n\n  /*\n   * set python dictionary\n   * @param p_dic, the dictionary\n   */\n  W_API void set_dictionary(const std::string& p_dic);\n  /*\n   * get python script\n   * @return the script\n   */\n  W_API std::string get_script() const;\n\n  /*\n   * run an inline python script\n   * @param p_script: python script\n   * @return 0 if success, otherwise return error code\n   */\n  W_API boost::leaf::result<int> run(_In_ const std::string_view& p_script,\n                                     std::unordered_map<std::string, std::any>& p_requested_vars);\n\n  ///*\n  // * run a python script from a file: no input parameter, no output parameter\n  // */\n  // void run_simple_script_file(const std::filesystem::path& /* path file */);\n  ///*\n  // * run a function from inline python script: no input parameter, one output parameter\n  // */\n  // template <typename RETTYPE>\n  //[[nodiscard]] RETTYPE run_function_and_get_result(\n  //    const std::string& /* function name */, const std::string& /* script */ = {});\n  ///*\n  // * run a function from a script file : no input parameter, one output parameter\n  // */\n  // template <typename RETTYPE>\n  //[[nodiscard]] RETTYPE run_function_from_script_file_and_get_result(\n  //    const std::filesystem::path& path_file, const std::string& func_name);\n  ///*\n  // * run a function from inline python script: variadic number of input parameter, variadic number\n  // * of output parameter\n  // */\n  // template <typename... ARGS>\n  //[[nodiscard]] boost::python::tuple call_function(\n  //    const std::string& func_name, const std::string& /* script */ = {}, ARGS&&... args);\n  ///*\n  // * run a function from a script file: variadic number of input parameter, variadic number of\n  // * output parameter\n  // */\n  // template <typename... ARGS>\n  //[[nodiscard]] boost::python::tuple call_function_from_script_file(\n  //    const std::filesystem::path& path_file, const std::string& func_name, ARGS&&... args);\n  ///*\n  // * run a function from inline python script and return the value of single variable\n  // */\n  // template <typename T>\n  //[[nodiscard]] T run_and_get_value(\n  //    const std::string& /* variable name */, const std::string& /* script */ = {});\n\n  ///*\n  // * run a function from a script file and return the value of single variable\n  // */\n  // template <typename T>\n  //[[nodiscard(\"No ignore return value!\")]] T run_file_script_and_get_value(\n  //    const std::filesystem::path& /* python file */, const std::string& /* variable name */);\n\n private:\n  // copy constructor\n  w_python(const w_python&) = delete;\n  // copy operator\n  w_python& operator=(const w_python&) = delete;\n\n  void _release();\n  static std::string _parse_python_exception();\n\n  std::string _script;\n  std::string _module_name = \"__main__\";\n  std::string _dictionary_name = \"__dict__\";\n\n  boost::python::pointer_wrapper<boost::python::api::object> _global =\n      boost::python::ptr(boost::python::api::object());\n};  // class w_python\n\n// template <typename RETTYPE>\n//[[nodiscard(\"No ignore return value!\")]] RETTYPE w_python::run_function_and_get_result(\n//     const std::string& func_name, const std::string& script) {\n//   if (!script.empty())\n//     script_ = script;\n//   Py_Initialize();\n//   namespace bp = boost::python;\n//   RETTYPE val{};\n//   try {\n//     bp::object main = bp::import(module_name_.c_str());\n//     bp::object global(main.attr(dictionary_name_.c_str()));\n//     bp::object result = bp::exec(script_.c_str(), global, global);\n//     bp::object func = global[func_name.c_str()];  // Create a reference to it.\n//     val = bp::extract<RETTYPE>(func());\n//     return val;\n//   } catch (bp::error_already_set&) {\n//     PyErr_Print();\n//     throw;\n// #ifdef USE_PY_FINALIZE\n//     if (Py_FinalizeEx() < 0) {\n//       PyErr_Print();\n//       throw std::runtime_error{bad_python_finalization};\n//     }\n// #endif  // USE_PY_FINALIZE\n//   }\n// #ifdef USE_PY_FINALIZE\n//   if (Py_FinalizeEx() < 0) {\n//     PyErr_Print();\n//     throw std::runtime_error{bad_python_finalization};\n//   }\n// #endif  // USE_PY_FINALIZE\n//   return val;\n// }\n//\n// template <typename RETTYPE>\n//[[nodiscard(\"No ignore return value!\")]] RETTYPE\n// w_python::run_function_from_script_file_and_get_result(const std::filesystem::path& path_file,\n//                                                        const std::string& func_name) {\n//   script_ = load_py_file(path_file);\n//   Py_Initialize();\n//   namespace bp = boost::python;\n//   RETTYPE ret{};\n//   try {\n//     bp::object main = bp::import(module_name_.c_str());\n//     bp::object global(main.attr(dictionary_name_.c_str()));\n//     std::wstring path_as_wide_str = path_file.c_str();\n//     std::string path_as_str;\n//     std::copy(path_as_wide_str.begin(), path_as_wide_str.end(), std::back_inserter(path_as_str));\n//     bp::object result = bp::exec_file(path_as_str.c_str(), global, global);\n//     bp::object func = global[func_name.c_str()];  // Create a reference to it.\n//     ret = bp::extract<RETTYPE>(func());\n//     return ret;\n//   } catch (bp::error_already_set&) {\n//     PyErr_Print();\n//     throw;\n// #ifdef USE_PY_FINALIZE\n//     if (Py_FinalizeEx() < 0) {\n//       PyErr_Print();\n//       throw std::runtime_error{bad_python_finalization};\n//     }\n// #endif  // USE_PY_FINALIZE\n//   }\n// #ifdef USE_PY_FINALIZE\n//   if (Py_FinalizeEx() < 0) {\n//     PyErr_Print();\n//     throw std::runtime_error{bad_python_finalization};\n//   }\n// #endif  // USE_PY_FINALIZE\n//   return ret;\n// }\n//\n// template <typename... ARGS>\n//[[nodiscard]] boost::python::tuple w_python::call_function(const std::string& func_name,\n//                                                                const std::string& script,\n//                                                                ARGS&&... args) {\n//   if (!script.empty())\n//     script_ = script;\n//\n//   Py_Initialize();\n//   namespace bp = boost::python;\n//   bp::tuple ret{};\n//   try {\n//     bp::object main = bp::import(module_name_.c_str());\n//     bp::object global(main.attr(dictionary_name_.c_str()));\n//\n//     bp::object result = bp::exec(script_.c_str(), global, global);\n//     bp::object func = global[func_name.c_str()];  // Create a reference to it.\n//     ret = bp::call<bp::tuple>(func.ptr(), args...);\n//   } catch (bp::error_already_set&) {\n//     PyErr_Print();\n//     throw;\n// #ifdef USE_PY_FINALIZE\n//     if (Py_FinalizeEx() < 0) {\n//       PyErr_Print();\n//       throw std::runtime_error{bad_python_finalization};\n//     }\n// #endif  // USE_PY_FINALIZE\n//   }\n// #ifdef USE_PY_FINALIZE\n//   if (Py_FinalizeEx() < 0) {\n//     PyErr_Print();\n//     throw std::runtime_error{bad_python_finalization};\n//   }\n// #endif  // USE_PY_FINALIZE\n//   return ret;\n// }\n//\n// template <typename... ARGS>\n//[[nodiscard(\"No ignore return value!\")]] boost::python::tuple\n// w_python::call_function_from_script_file(const std::filesystem::path& path_file,\n//                                              const std::string& func_name, ARGS&&... args) {\n//   script_ = load_py_file(path_file);\n//   Py_Initialize();\n//   namespace bp = boost::python;\n//   bp::tuple ret{};\n//   try {\n//     bp::object main = bp::import(module_name_.c_str());\n//     bp::object global(main.attr(dictionary_name_.c_str()));\n//     bp::object result = bp::exec_file(path_file.filename().c_str(), global, global);\n//     bp::object func = global[func_name.c_str()];  // Create a reference to it.\n//     ret = bp::extract<bp::tuple>(func());\n//     return ret;\n//   } catch (bp::error_already_set&) {\n//     PyErr_Print();\n//     throw;\n// #ifdef USE_PY_FINALIZE\n//     if (Py_FinalizeEx() < 0) {\n//       PyErr_Print();\n//       throw std::runtime_error{bad_python_finalization};\n//     }\n// #endif  // USE_PY_FINALIZE\n//   }\n// #ifdef USE_PY_FINALIZE\n//   if (Py_FinalizeEx() < 0) {\n//     PyErr_Print();\n//     throw std::runtime_error{bad_python_finalization};\n//   }\n// #endif  // USE_PY_FINALIZE\n//   return ret;\n// }\n//\n// template <typename T>\n//[[nodiscard(\"No ignore return value!\")]] T w_python::run_file_script_and_get_value(\n//     const std::filesystem::path& path_file, const std::string& var_name) {\n//   script_ = load_py_file(path_file);\n//   Py_Initialize();\n//   namespace bp = boost::python;\n//   try {\n//     boost::python::object main = boost::python::import(\"__main__\");\n//     boost::python::object global(main.attr(\"__dict__\"));\n//     bp::object result = bp::exec_file(path_file.filename().c_str(), global, global);\n//     T val = boost::python::extract<T>(global[var_name]);\n//\n//     return val;\n//   } catch (bp::error_already_set&) {\n//     PyErr_Print();\n//     throw;\n// #ifdef USE_PY_FINALIZE\n//     if (Py_FinalizeEx() < 0) {\n//       PyErr_Print();\n//       throw std::runtime_error{bad_python_finalization};\n//     }\n// #endif  // USE_PY_FINALIZE\n//   }\n// #ifdef USE_PY_FINALIZE\n//   if (Py_FinalizeEx() < 0) {\n//     PyErr_Print();\n//     throw std::runtime_error{bad_python_finalization};\n//   }\n// #endif  // USE_PY_FINALIZE\n// }\n//[[nodiscard(\"No ignore return value!\")]] std::string load_py_file(\n//     const std::filesystem::path& path_file) {\n//   if (!std::filesystem::exists(path_file))\n//     throw std::runtime_error{\"bad filename!\"};\n//   auto path_file_as_str = path_file.c_str();\n//   std::ifstream f{path_file_as_str};\n//   std::string content;\n//   char ch;\n//   while (f.get(ch))\n//     content.push_back(ch);\n//\n//   return content;\n// }\n//\n////void run_simple_script(const std::string& script) {\n////  w_python pr;\n////  pr.set_script(script);\n////  pr.run_simple_script();\n////}\n//\n// void run_simple_script_from_file(const std::filesystem::path& python_file) {\n//  w_python pr;\n//  pr.run_simple_script_file(python_file);\n//}\n//\n// template <typename RETTYPE>\n//[[nodiscard(\"No ignore return value!\")]] RETTYPE run_function_and_get_result(\n//    const std::string& script, const std::string& func_name) {\n//  w_python pr{script};\n//  auto val = pr.run_function_and_get_result<RETTYPE>(func_name);\n//  return val;\n//}\n//\n// template <typename RETTYPE>\n//[[nodiscard(\"No ignore return value!\")]] RETTYPE run_function_from_file_script_and_get_result(\n//    const std::filesystem::path& path_file, const std::string& func_name) {\n//  w_python pr;\n//  auto val = pr.run_function_from_script_file_and_get_result<RETTYPE>(path_file, func_name);\n//  return val;\n//}\n//\n// template <typename... ARGS>\n//[[nodiscard(\"No ignore return value!\")]] boost::python::tuple call_function(\n//    const std::string& func_name, const std::string& script, ARGS&&... args) {\n//  w_python pr;\n//  auto val = pr.call_function(func_name, script, args...);\n//  return val;\n//}\n//\n// template <typename... ARGS>\n//[[nodiscard(\"No ignore return value!\")]] boost::python::tuple call_function_from_script_file(\n//    const std::filesystem::path& path_file, const std::string& func_name, ARGS&&... args) {\n//  w_python pr;\n//  auto val = pr.call_function(path_file, func_name, args...);\n//  return val;\n//}\n//\n// template <typename T>\n//[[nodiscard(\"No ignore return value!\")]] T run_and_get_value(const std::string& var_name,\n//                                                             const std::string& script) {\n//  w_python pr;\n//  auto val = pr.run_and_get_value<T>(var_name, script);\n//  return val;\n//}\n//\n// template <typename T>\n//[[nodiscard(\"No ignore return value!\")]] T run_file_script_and_get_value(\n//    const std::filesystem::path& path_file, const std::string& var_name) {\n//  w_python pr;\n//  auto val = pr.run_file_script_and_get_value<T>(path_file, var_name);\n//  return val;\n//}\n//\n// template <typename... RETTYPE>\n// std::tuple<RETTYPE...> convertBPTuple2StdTuple(const boost::python::tuple& pt) {\n//  std::tuple<RETTYPE...> t;\n//  for (int i = 0; i < boost::python::len(pt); ++i) {\n//    auto a = boost::python::extract<decltype(pt[i])>(pt[i]);\n//    std::tuple_cat(t, a);\n//  }\n//\n//  return t;\n//}\n\n}  // namespace wolf::system::python\n"
  },
  {
    "path": "wolf/system/socket/w_socket_options.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#ifdef WOLF_SYSTEM_SOCKET\n\n#include <functional>\n#include <random>\n#include <wolf/wolf.hpp>\n\n#include \"DISABLE_ANALYSIS_BEGIN\"\n#include <boost/asio.hpp>\n#include <boost/system/errc.hpp>\n#ifdef WOLF_SYSTEM_HTTP_WS\n#include <boost/asio/experimental/awaitable_operators.hpp>\n#include <boost/beast.hpp>\n#endif\n#include \"DISABLE_ANALYSIS_END\"\n\nnamespace wolf::system::socket {\n\ninline std::string make_connection_id() {\n  constexpr auto _max = 999;\n  constexpr auto _min = 100;\n\n  std::default_random_engine _rand_engine{};\n  std::uniform_int_distribution<int> _rand_gen(_min, _max);\n\n  const auto _now = std::chrono::system_clock::now();\n  return wolf::format(\"{}_{}\", _now, _rand_gen(_rand_engine));\n}\n\nstruct w_socket_options {\n  bool keep_alive = true;\n  bool no_delay = true;\n  bool reuse_address = true;\n  int max_connections = boost::asio::socket_base::max_listen_connections;\n\n  void set_to_socket(_Inout_ boost::asio::ip::tcp::socket &p_socket) {\n    // set acceptor's options\n    const auto _keep_alive_option =\n        boost::asio::socket_base::keep_alive(this->keep_alive);\n\n    const auto _reuse_address_option =\n        boost::asio::socket_base::reuse_address(this->reuse_address);\n\n    const auto _no_delay_opt = boost::asio::ip::tcp::no_delay(this->no_delay);\n\n    p_socket.set_option(_no_delay_opt);\n    p_socket.set_option(_keep_alive_option);\n    p_socket.set_option(_reuse_address_option);\n  }\n\n  template <typename T>\n  void\n  set_to_acceptor(_Inout_ boost::asio::basic_socket_acceptor<T> &p_acceptor) {\n    const auto _keep_alive_option =\n        boost::asio::socket_base::keep_alive(this->keep_alive);\n    p_acceptor.set_option(_keep_alive_option);\n\n    const auto _reuse_address_option =\n        boost::asio::socket_base::reuse_address(this->reuse_address);\n    p_acceptor.set_option(_reuse_address_option);\n  }\n};\n\n#ifdef WOLF_SYSTEM_HTTP_WS\nusing w_ws_stream = boost::beast::websocket::stream<\n    typename boost::beast::tcp_stream::rebind_executor<\n        typename boost::asio::use_awaitable_t<>::executor_with_default<\n            boost::asio::any_io_executor>>::other>;\n\ntypedef std::function<boost::beast::websocket::close_code(\n    _In_ const std::string &p_conn_id, _Inout_ w_buffer &p_mut_data,\n    _Inout_ bool &p_is_binary)>\n    w_session_ws_on_data_callback;\n#endif\n\ntypedef std::function<boost::system::errc::errc_t(\n    _In_ const std::string &p_conn_id, _Inout_ w_buffer &p_mut_data)>\n    w_session_on_data_callback;\n\ntypedef std::function<void(_In_ const std::string &p_conn_id,\n                           _In_ const boost::system::system_error &p_error)>\n    w_session_on_error_callback;\n\n} // namespace wolf::system::socket\n\n#endif"
  },
  {
    "path": "wolf/system/socket/w_tcp_client.cpp",
    "content": "﻿#ifdef WOLF_SYSTEM_SOCKET\n\n#include \"w_tcp_client.hpp\"\n#include <chrono>\n\n#include \"DISABLE_ANALYSIS_BEGIN\"\n#include <boost/asio/experimental/awaitable_operators.hpp>\n#include \"DISABLE_ANALYSIS_END\"\n\nusing namespace boost::asio::experimental::awaitable_operators;\nusing w_tcp_client = wolf::system::socket::w_tcp_client;\nusing tcp = boost::asio::ip::tcp;\n\nw_tcp_client::w_tcp_client(boost::asio::io_context &p_io_context) noexcept\n    : _resolver(std::make_unique<tcp::resolver>(p_io_context)),\n      _socket(std::make_unique<tcp::socket>(p_io_context)) {}\n\nw_tcp_client::~w_tcp_client() noexcept {\n  try {\n    const auto _resolver_nn =\n        gsl::not_null<tcp::resolver *>(this->_resolver.get());\n    const auto _socket_nn = gsl::not_null<tcp::socket *>(this->_socket.get());\n\n    _resolver_nn->cancel();\n    if (_socket_nn->is_open()) {\n      _socket_nn->close();\n    }\n    _socket_nn->release();\n  } catch (...) {\n  }\n}\n\nboost::asio::awaitable<boost::asio::ip::basic_resolver_results<tcp>> \nw_tcp_client::async_resolve(_In_ const tcp::endpoint &p_endpoint) {\n  const auto _resolver_nn =\n      gsl::not_null<tcp::resolver *>(this->_resolver.get());\n  return _resolver_nn->async_resolve(p_endpoint, boost::asio::use_awaitable);\n}\n\nboost::asio::awaitable<boost::asio::ip::basic_resolver_results<tcp>>\nw_tcp_client::async_resolve(_In_ const std::string &p_address,\n                            _In_ const uint16_t &p_port) {\n  const auto _resolver_nn =\n      gsl::not_null<tcp::resolver *>(this->_resolver.get());\n\n  const auto _address = boost::asio::ip::make_address(p_address);\n  const tcp::endpoint _endpoint(_address, p_port);\n  return _resolver_nn->async_resolve(_endpoint, boost::asio::use_awaitable);\n}\n\nboost::asio::awaitable<void, boost::asio::any_io_executor>\nw_tcp_client::async_connect(_In_ const tcp::endpoint &p_endpoint,\n                            _In_ const w_socket_options &p_socket_options) {\n  const gsl::not_null<tcp::socket *> _socket_nn(this->_socket.get());\n\n  // get protocol\n  const auto _protocol = p_endpoint.protocol();\n\n  // open socket and connect to the endpoint asynchronously\n  _socket_nn->open(_protocol);\n\n  // set socket options\n  _socket_nn->set_option(\n      boost::asio::socket_base::reuse_address(p_socket_options.reuse_address));\n  _socket_nn->set_option(\n      boost::asio::socket_base::keep_alive(p_socket_options.keep_alive));\n  _socket_nn->set_option(tcp::no_delay(p_socket_options.no_delay));\n\n  return this->_socket->async_connect(p_endpoint, boost::asio::use_awaitable);\n}\n\nboost::asio::awaitable<size_t>\nw_tcp_client::async_write(_In_ const w_buffer &p_buffer) {\n  const gsl::not_null<tcp::socket *> _socket_nn(this->_socket.get());\n\n  return _socket_nn->async_send(\n      boost::asio::buffer(p_buffer.buf, p_buffer.used_bytes),\n      boost::asio::use_awaitable);\n}\n\nboost::asio::awaitable<size_t>\nw_tcp_client::async_read(_Inout_ w_buffer &p_mut_buffer) {\n  const gsl::not_null<tcp::socket *> _socket_nn(this->_socket.get());\n\n  return _socket_nn->async_receive(boost::asio::buffer(p_mut_buffer.buf),\n                                   boost::asio::use_awaitable);\n}\n\nbool w_tcp_client::get_is_open() const {\n  const gsl::not_null<tcp::socket *> _socket_nn(this->_socket.get());\n  return _socket_nn->is_open();\n}\n\n#endif\n"
  },
  {
    "path": "wolf/system/socket/w_tcp_client.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#ifdef WOLF_SYSTEM_SOCKET\n\n#include \"w_socket_options.hpp\"\n#include <variant>\n#include <wolf/wolf.hpp>\n\n#include \"DISABLE_ANALYSIS_BEGIN\"\n#include \"DISABLE_ANALYSIS_END\"\n#include <boost/asio.hpp>\n\nnamespace wolf::system::socket {\nclass w_tcp_client {\npublic:\n  // default constructor\n  W_API explicit w_tcp_client(boost::asio::io_context &p_io_context) noexcept;\n\n  // move constructor.\n  W_API w_tcp_client(w_tcp_client &&p_other) = default;\n  // move assignment operator.\n  W_API w_tcp_client &operator=(w_tcp_client &&p_other) = default;\n\n  // destructor\n  W_API virtual ~w_tcp_client() noexcept;\n\n  /*\n   * resolve an endpoint asynchronously\n   * @param p_endpoint, the endpoint\n   * @returns a coroutine contains the results of reolver\n   */\n  W_API\n  boost::asio::awaitable<\n      boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>>\n  async_resolve(_In_ const boost::asio::ip::tcp::endpoint &p_endpoint);\n\n  /*\n   * resolve an address with port asynchronously\n   * @param p_address, the address\n   * @param p_port, the port\n   * @returns a coroutine contains the results of reolver\n   */\n  W_API\n  boost::asio::awaitable<\n      boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>>\n  async_resolve(_In_ const std::string &p_address, _In_ const uint16_t &p_port);\n\n  /*\n   * open a socket and connect to the endpoint asynchronously\n   * @param p_endpoint, the endpoint of the server\n   * @param p_socket_options, the socket options\n   * @returns a coroutine\n   */\n  W_API\n  boost::asio::awaitable<void, boost::asio::any_io_executor>\n  async_connect(_In_ const boost::asio::ip::tcp::endpoint &p_endpoint,\n                _In_ const w_socket_options &p_socket_options);\n\n  /*\n   * write buffer data into the socket\n   * @param p_buffer, the source buffer which should be written\n   * @returns number of the written bytes\n   */\n  W_API\n  boost::asio::awaitable<size_t> async_write(_In_ const w_buffer &p_buffer);\n\n  /*\n   * read from the socket into the buffer\n   * @param p_mut_buffer, the destination buffer which will contain bytes\n   * @returns number of read bytes\n   */\n  W_API\n  boost::asio::awaitable<size_t> async_read(_Inout_ w_buffer &p_mut_buffer);\n\n  /*\n   * get whether socket is open\n   * @returns true if socket was open\n   */\n  W_API\n  bool get_is_open() const;\n\nprivate:\n  // copy constructor\n  w_tcp_client(const w_tcp_client &) = delete;\n  // copy operator\n  w_tcp_client &operator=(const w_tcp_client &) = delete;\n\n  std::unique_ptr<boost::asio::ip::tcp::socket> _socket;\n  std::unique_ptr<boost::asio::ip::tcp::resolver> _resolver;\n};\n} // namespace wolf::system::socket\n\n#endif"
  },
  {
    "path": "wolf/system/socket/w_tcp_server.cpp",
    "content": "#ifdef WOLF_SYSTEM_SOCKET\n\n#include \"w_tcp_server.hpp\"\n#include <random>\n\n#include \"DISABLE_ANALYSIS_BEGIN\"\n#ifdef WOLF_SYSTEM_SSL\n    #include <boost/asio/ssl.hpp>\n#endif\n#include <boost/asio/experimental/awaitable_operators.hpp>\n#include \"DISABLE_ANALYSIS_END\"\n\nusing w_tcp_server = wolf::system::socket::w_tcp_server;\nusing w_session_on_data_callback = wolf::system::socket::w_session_on_data_callback;\nusing w_session_on_error_callback = wolf::system::socket::w_session_on_error_callback;\nusing w_socket_options = wolf::system::socket::w_socket_options;\nusing steady_clock = std::chrono::steady_clock;\nusing steady_timer = boost::asio::steady_timer;\nusing io_context = boost::asio::io_context;\nusing tcp = boost::asio::ip::tcp;\nusing time_point = std::chrono::steady_clock::time_point;\nusing namespace boost::asio::experimental::awaitable_operators;\n\nstatic boost::asio::awaitable<std::errc>\nwatchdog(_Inout_ const time_point &p_deadline) noexcept {\n  steady_timer _timer(co_await boost::asio::this_coro::executor);\n  auto _now = steady_clock::now();\n\n#ifdef __clang__\n#pragma unroll\n#endif\n  while (p_deadline > _now) {\n    _timer.expires_at(p_deadline);\n    co_await _timer.async_wait(boost::asio::use_awaitable);\n    _now = steady_clock::now();\n  }\n  co_return std::errc::timed_out;\n}\n\nstatic boost::asio::awaitable<void> on_handle_session(\n    const boost::asio::io_context &p_io_context, tcp::socket &p_socket,\n    const std::string &p_conn_id, time_point &p_deadline,\n    steady_clock::duration p_timeout,\n    const w_session_on_data_callback p_on_data_callback,\n    const w_session_on_error_callback p_on_error_callback) noexcept {\n  w_buffer _buffer = {};\n\n#ifdef __clang__\n#pragma unroll\n#endif\n  while (!p_io_context.stopped()) {\n    p_deadline = steady_clock::now() + p_timeout;\n\n    try {\n      _buffer.used_bytes = co_await p_socket.async_receive(\n          boost::asio::buffer(_buffer.buf), boost::asio::use_awaitable);\n\n      // call callback\n      const auto _res = p_on_data_callback(p_conn_id, _buffer);\n      if (_res == boost::system::errc::connection_aborted) {\n        break;\n      }\n      co_await p_socket.async_send(\n          boost::asio::buffer(_buffer.buf, _buffer.used_bytes),\n          boost::asio::use_awaitable);\n    } catch (const boost::system::system_error &p_ex) {\n      p_on_error_callback(p_conn_id, p_ex);\n      break;\n    }\n  }\n}\n\nstatic boost::asio::awaitable<void>\ns_session(const boost::asio::io_context &p_io_context, tcp::socket p_socket,\n          steady_clock::duration p_timeout,\n          w_session_on_data_callback p_on_data_callback,\n          w_session_on_error_callback p_on_error_callback) noexcept {\n\n  const auto _conn_id = wolf::system::socket::make_connection_id();\n\n  time_point _deadline = {};\n  const auto _ret = co_await (\n      on_handle_session(p_io_context, p_socket, _conn_id, _deadline, p_timeout,\n                        p_on_data_callback, p_on_error_callback) ||\n      watchdog(_deadline));\n  if (std::get<1>(_ret) == std::errc::timed_out) {\n    const auto _error = boost::system::system_error(\n        make_error_code(boost::system::errc::timed_out));\n    p_on_error_callback(_conn_id, _error);\n  }\n\n  co_return;\n}\n\nstatic boost::asio::awaitable<void> s_listen(\n    _In_ const boost::asio::io_context &p_io_context, _In_ tcp::endpoint &p_endpoint,\n    _In_ const steady_clock::duration &p_timeout, _In_ w_socket_options &p_socket_options,\n    _In_ w_session_on_data_callback p_on_data_callback,\n    _In_ w_session_on_error_callback p_on_error_callback) noexcept {\n  // create acceptor from this coroutine\n  auto _executor = co_await boost::asio::this_coro::executor;\n  tcp::acceptor _acceptor(_executor, p_endpoint);\n\n  // set acceptor's options\n  p_socket_options.set_to_acceptor(_acceptor);\n\n  // start listening for connections\n  _acceptor.listen(p_socket_options.max_connections);\n\n#ifdef __clang__\n#pragma unroll\n#endif\n  while (!p_io_context.stopped()) {\n    tcp::socket _socket = co_await _acceptor.async_accept(boost::asio::use_awaitable);\n    p_socket_options.set_to_socket(_socket);\n\n    //auto _ssl_session = boost::asio::ssl::stream<tcp::socket>(std::move(_socket), _ssl_context);\n\n    // spawn a coroutinue for handling session\n    co_spawn(_executor,\n             s_session(p_io_context, std::move(_socket), p_timeout, p_on_data_callback,\n                       p_on_error_callback),\n             boost::asio::detached);\n  }\n}\n\nboost::leaf::result<int> w_tcp_server::run(\n    _In_ boost::asio::io_context &p_io_context, _In_ boost::asio::ip::tcp::endpoint &&p_endpoint,\n    _In_ std::chrono::steady_clock::duration &&p_timeout, _In_ w_socket_options &&p_socket_options,\n    _In_ w_session_on_data_callback p_on_data_callback,\n    _In_ w_session_on_error_callback p_on_error_callback) noexcept {\n  try {\n#ifdef WOLF_SYSTEM_SSL\n    // try create ssl context\n    // auto _ssl = boost::asio::ssl::context(p_socket_options.tls_version);\n    //_ssl.use_certificate_chain_file(p_socket_options.certificate_chain_file.string());\n    //_ssl.use_private_key_file(p_socket_options.private_key_file.string(),\n    //                          boost::asio::ssl::context::pem);\n#endif  // WOLF_SYSTEM_SSL\n\n    // server with coroutines\n    boost::asio::co_spawn(p_io_context,\n                          s_listen(p_io_context, p_endpoint, p_timeout, p_socket_options,\n                                   p_on_data_callback, p_on_error_callback),\n                          boost::asio::detached);\n    return 0;\n\n  } catch (_In_ const std::exception &p_ex) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"tcp server caught an exception : \" + std::string(p_ex.what()));\n  }\n}\n\n#endif // WOLF_SYSTEM_SOCKET\n"
  },
  {
    "path": "wolf/system/socket/w_tcp_server.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n#ifdef WOLF_SYSTEM_SOCKET\n\n#pragma once\n\n#include \"w_socket_options.hpp\"\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system::socket {\nclass w_tcp_server {\n public:\n  /*\n   * @param p_io_context, the boost io context\n   * @param p_endpoint, the endpoint of the server\n   * @param p_timeout, the timeout for connection\n   * @param p_socket_options, the socket options\n   * @param p_on_data_callback, on data callback for session\n   * @param p_on_error_callback, on error callback for session\n   * @returns void\n   */\n  W_API static boost::leaf::result<int> run(\n      _In_ boost::asio::io_context &p_io_context, _In_ boost::asio::ip::tcp::endpoint &&p_endpoint,\n      _In_ std::chrono::steady_clock::duration &&p_timeout,\n      _In_ w_socket_options &&p_socket_options, _In_ w_session_on_data_callback p_on_data_callback,\n      _In_ w_session_on_error_callback p_on_error_callback) noexcept;\n};\n}  // namespace wolf::system::socket\n#endif // WOLF_SYSTEM_SOCKET"
  },
  {
    "path": "wolf/system/socket/w_ws_client.cpp",
    "content": "#if defined(WOLF_SYSTEM_HTTP_WS) && defined(WOLF_SYSTEM_SOCKET)\n\n#include \"w_ws_client.hpp\"\n\nusing w_ws_client = wolf::system::socket::w_ws_client;\nusing tcp = boost::asio::ip::tcp;\n\nw_ws_client::w_ws_client(boost::asio::io_context &p_io_context) noexcept\n    : _resolver(std::make_unique<tcp::resolver>(p_io_context)) {}\n\nw_ws_client::~w_ws_client() noexcept {\n  try {\n    const auto _resolver_nn =\n        gsl::not_null<tcp::resolver *>(this->_resolver.get());\n    _resolver_nn->cancel();\n\n    if (this->_ws != nullptr && this->_ws->is_open()) {\n      this->_ws->close(boost::beast::websocket::close_code::normal);\n    }\n  } catch (...) {\n  }\n}\n\nboost::asio::awaitable<boost::asio::ip::basic_resolver_results<tcp>>\nw_ws_client::async_resolve(_In_ const tcp::endpoint &p_endpoint) {\n  const auto _resolver_nn =\n      gsl::not_null<tcp::resolver *>(this->_resolver.get());\n  return _resolver_nn->async_resolve(p_endpoint, boost::asio::use_awaitable);\n}\n\nboost::asio::awaitable<boost::asio::ip::basic_resolver_results<tcp>>\nw_ws_client::async_resolve(_In_ const std::string &p_address,\n                           _In_ const uint16_t &p_port) {\n  const auto _resolver_nn =\n      gsl::not_null<tcp::resolver *>(this->_resolver.get());\n\n  const auto _address = boost::asio::ip::make_address(p_address);\n  const tcp::endpoint _endpoint(_address, p_port);\n  return _resolver_nn->async_resolve(_endpoint, boost::asio::use_awaitable);\n}\n\nboost::asio::awaitable<void> w_ws_client::async_connect(\n    _In_ const boost::asio::ip::tcp::endpoint &p_endpoint,\n    _In_ const w_socket_options &p_socket_options) {\n\n  this->_ws =\n      std::make_unique<w_ws_stream>(boost::asio::use_awaitable.as_default_on(\n          boost::beast::websocket::stream<boost::beast::tcp_stream>(\n              co_await boost::asio::this_coro::executor)));\n\n  co_await boost::beast::get_lowest_layer(*this->_ws)\n      .async_connect(p_endpoint, boost::asio::use_awaitable);\n\n  // turn off the timeout on the tcp_stream, because\n  // the websocket stream has its own timeout system.\n  boost::beast::get_lowest_layer(*this->_ws).expires_never();\n\n  // set suggested timeout settings for the websocket\n  this->_ws->set_option(\n      boost::beast::websocket::stream_base::timeout::suggested(\n          boost::beast::role_type::client));\n\n  // set a decorator to change the User-Agent of the handshake\n  this->_ws->set_option(boost::beast::websocket::stream_base::decorator(\n      [](boost::beast::websocket::request_type &req) {\n        req.set(boost::beast::http::field::user_agent,\n                std::string(BOOST_BEAST_VERSION_STRING) + \" wolf-ws-client\");\n      }));\n\n  // perform the websocket handshake\n  co_await this->_ws->async_handshake(p_endpoint.address().to_string(), \"/\");\n}\n\nboost::asio::awaitable<size_t>\nw_ws_client::async_write(_In_ const w_buffer &p_buffer, _In_ bool p_is_binary) {\n  if (p_is_binary) {\n    this->_ws->binary(true);\n  } else {\n    this->_ws->text(true);\n  }\n  co_await this->_ws->async_write(\n      boost::asio::const_buffer(p_buffer.buf.data(), p_buffer.used_bytes));\n}\n\nboost::asio::awaitable<size_t>\nw_ws_client::async_read(_Inout_ w_buffer &p_mut_buffer) {\n  boost::beast::flat_buffer _buffer = {};\n  co_await this->_ws->async_read(_buffer);\n\n  // an extra copy just for having a stable ABI\n  const auto _size = std::min(_buffer.cdata().size(), p_mut_buffer.buf.size());\n  std::memcpy(p_mut_buffer.buf.data(),\n              static_cast<char const *>(_buffer.cdata().data()), _size);\n  co_return _size;\n}\n\nboost::asio::awaitable<size_t>\nw_ws_client::async_read(_Inout_ boost::beast::flat_buffer &p_mut_buffer) {\n  co_await this->_ws->async_read(p_mut_buffer);\n}\n\nboost::asio::awaitable<void> w_ws_client::async_close(\n    _In_ const boost::beast::websocket::close_reason &p_close_reason) {\n  if (this->_ws == nullptr) {\n    co_return;\n  }\n  co_await this->_ws->async_close(p_close_reason);\n}\n\nbool w_ws_client::is_open() const {\n  if (this->_ws == nullptr) {\n    return false;\n  }\n  return this->_ws->is_open();\n}\n\n#endif //defined(WOLF_SYSTEM_HTTP_WS) && defined(WOLF_SYSTEM_SOCKET)\n"
  },
  {
    "path": "wolf/system/socket/w_ws_client.hpp",
    "content": "#if defined(WOLF_SYSTEM_HTTP_WS) && defined(WOLF_SYSTEM_SOCKET)\n\n#pragma once\n\n#include \"w_socket_options.hpp\"\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system::socket {\nclass w_ws_client {\npublic:\n  // default constructor\n  W_API explicit w_ws_client(boost::asio::io_context &p_io_context) noexcept;\n\n  // move constructor.\n  W_API w_ws_client(w_ws_client &&p_other) = default;\n  // move assignment operator.\n  W_API w_ws_client &operator=(w_ws_client &&p_other) = default;\n\n  // destructor\n  W_API virtual ~w_ws_client() noexcept;\n\n  /*\n   * resolve an endpoint asynchronously\n   * @param p_endpoint, the endpoint\n   * @returns a coroutine contains the results of reolver\n   */\n  W_API\n  boost::asio::awaitable<\n      boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>>\n  async_resolve(_In_ const boost::asio::ip::tcp::endpoint &p_endpoint);\n\n  /*\n   * resolve an address asynchronously\n   * @param p_address, the address\n   * @param p_port, the port\n   * @returns a coroutine contains the results of reolver\n   */\n  W_API\n  boost::asio::awaitable<\n      boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>>\n  async_resolve(_In_ const std::string &p_address, _In_ const uint16_t &p_port);\n\n  /*\n   * open a websocket and handshake with the endpoint asynchronously\n   * @param p_endpoint, the endpoint of the server\n   * @param p_socket_options, the socket options\n   * @returns a coroutine\n   */\n  W_API\n  boost::asio::awaitable<void>\n  async_connect(_In_ const boost::asio::ip::tcp::endpoint &p_endpoint,\n                _In_ const w_socket_options &p_socket_options);\n\n  /*\n   * write buffer data into the websocket\n   * @param p_buffer, the source buffer which should be written\n   * @returns a number of the written bytes\n   */\n  W_API\n  boost::asio::awaitable<size_t> async_write(_In_ const w_buffer &p_buffer,\n                                             _In_ bool p_is_binary);\n\n  /*\n   * read from the websocket into the buffer\n   * @param p_mut_buffer, the destination buffer which will contain bytes\n   * @returns a coroutine with number of read bytes\n   */\n  W_API\n  boost::asio::awaitable<size_t> async_read(_Inout_ w_buffer &p_mut_buffer);\n\n  /*\n   * read from the websocket into the buffer\n   * @param p_mut_buffer, the destination buffer which will contain bytes\n   * @returns a coroutine with number of read bytes\n   */\n  W_API\n  boost::asio::awaitable<size_t>\n  async_read(_Inout_ boost::beast::flat_buffer &p_mut_buffer);\n\n  /*\n   * close the websocket asynchronously\n   * @param p_close_reason, the close reason\n   * @returns a coroutine\n   */\n  W_API\n  boost::asio::awaitable<void>\n  async_close(_In_ const boost::beast::websocket::close_reason &p_close_reason);\n\n  /*\n   * get whether websocket is open or not\n   * @returns true if socket was open\n   */\n  W_API bool is_open() const;\n\nprivate:\n  // copy constructor\n  w_ws_client(const w_ws_client &) = delete;\n  // copy operator\n  w_ws_client &operator=(const w_ws_client &) = delete;\n\n  std::unique_ptr<w_ws_stream> _ws;\n  std::unique_ptr<boost::asio::ip::tcp::resolver> _resolver;\n};\n} // namespace wolf::system::socket\n\n#endif // defined(WOLF_SYSTEM_HTTP_WS) && defined(WOLF_SYSTEM_SOCKET)\n"
  },
  {
    "path": "wolf/system/socket/w_ws_client_emc.cpp",
    "content": "#if defined(WOLF_SYSTEM_HTTP1_WS)// && defined(EMSCRIPTEN)\n\n#include \"w_ws_client_emc.hpp\"\n//#include <emscripten/emscripten.h>\n\nextern \"C\" {\nextern int wsCreateWebSocket(const char *url);\nextern void wsDeleteWebSocket(int ws);\nextern void wsSetOpenCallback(int ws, void (*openCallback)(void *));\nextern void wsSetErrorCallback(int ws, void (*errorCallback)(const char *, void *));\nextern void wsSetMessageCallback(int ws, void (*messageCallback)(const char *, int, void *));\nextern int wsSendMessage(int ws, const char *buffer, int size);\nextern void wsSetUserPointer(int ws, void *ptr);\n}\n\nusing w_ws_client_emc = wolf::system::socket::w_ws_client_emc;\n\nvoid w_ws_client_emc::s_on_open_callback(_In_ void *p_ptr) noexcept {\n  const auto _ws = gsl::narrow_cast<w_ws_client_emc *>(p_ptr);\n  if (_ws) {\n    _ws->_connected = true;\n    _ws->_on_open_handler();\n  }\n}\n\nvoid w_ws_client_emc::s_on_error_callback(_In_ const char *p_error, _In_ void *p_ptr) noexcept {\n  const auto _ws = gsl::narrow_cast<w_ws_client_emc *>(p_ptr) ;\n  if (_ws) {\n    auto _error_msg = std::string(p_error ? p_error : \"unknown\");\n    _ws->_on_error_handler(std::move(_error_msg));\n  }\n}\n\nvoid w_ws_client_emc::s_on_message_callback(_In_ const char *p_data, _In_ int p_size,\n                                            _In_ void *p_ptr) noexcept {\n  const auto _ws = gsl::narrow_cast<w_ws_client_emc *>(p_ptr);\n  if (_ws == nullptr) {\n    return;\n  }\n\n  if (p_data) {\n    if (p_size >= 0) {\n      auto _bytes = reinterpret_cast<const std::byte *>(p_data);\n      _ws->triggerMessage(w_binary(_bytes, _bytes + p_size));\n    } else {\n      _ws->triggerMessage(std::string(p_data));\n    }\n  } else {\n    _ws->_on_close_handler();\n    _ws->close();\n  }\n}\n\nboost::leaf::result<int> w_ws_client_emc::open(\n    _In_ const std::string &p_url, _In_ wolf::w_function<void(void) noexcept> &&p_on_open_handler,\n    _In_ wolf::w_function<void(void) noexcept> &&p_on_message_handler,\n    _In_ wolf::w_function<void(std::string) noexcept> &&p_on_error_handler,\n    _In_ wolf::w_function<void(void) noexcept> &&p_on_close_handler) noexcept {\n  if (p_url.empty()) {\n    return W_FAILURE(std::errc::invalid_argument, \"missing websocket url endpoint\");\n  }\n\n  // close current websocket\n  close();\n\n  this->_on_open_handler = std::move(p_on_open_handler);\n  // this->_on_message_handler = std::move(p_on_message_handler);\n  this->_on_error_handler = std::move(p_on_error_handler);\n  // this->_on_close_handler = std::move(p_on_close_handler);\n\n  this->_id = wsCreateWebSocket(p_url.c_str());\n  if (this->_id <= 0) {\n    return W_FAILURE(std::errc::operation_canceled, \"websocket is not supported\");\n  }\n\n  wsSetUserPointer(this->_id, this);\n  wsSetOpenCallback(this->_id, s_on_open_callback);\n  wsSetErrorCallback(this->_id, s_on_error_callback);\n  wsSetMessageCallback(this->_id, s_on_message_callback);\n\n  return 0;\n}\n\n#endif // defined(WOLF_SYSTEM_HTTP1_WS) && defined(EMSCRIPTEN)\n"
  },
  {
    "path": "wolf/system/socket/w_ws_client_emc.hpp",
    "content": "#if defined(WOLF_SYSTEM_HTTP1_WS)// && defined(EMSCRIPTEN)\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n#include <variant>\n#include <vector>\n#include <cstddef>\n\nnamespace wolf::system::socket {\n\nusing w_ws_message_variant = std::variant<w_binary, std::string>;\n\nclass w_ws_client_emc {\n public:\n  W_API w_ws_client_emc() noexcept = default;\n  W_API virtual ~w_ws_client_emc() noexcept { std::ignore = close(); }\n\n  // move constructor.\n  W_API w_ws_client_emc(w_ws_client_emc &&p_other) noexcept {\n    _move(std::forward<w_ws_client_emc &&>(p_other));\n  }\n  // move assignment operator.\n  W_API w_ws_client_emc &operator=(w_ws_client_emc &&p_other) noexcept {\n    _move(std::forward<w_ws_client_emc &&>(p_other));\n    return *this;\n  }\n\n  boost::leaf::result<int> open(_In_ const std::string &p_url,\n                                _In_ w_function<void(void) noexcept> &&p_on_open_handler,\n                                _In_ w_function<void(void) noexcept> &&p_on_message_handler,\n                                _In_ w_function<void(std::string) noexcept> &&p_on_error_handler,\n                                _In_ w_function<void(void) noexcept> &&p_on_close_handler) noexcept;\n\n  W_API boost::leaf::result<int> close() noexcept;\n\n  // bool send(_In_ w_ws_message_variant p_data) noexcept;\n  // bool send(_In_ const byte *p_data, _In_ size_t p_size) noexcept;\n\n  // bool is_open() const noexcept;\n  // bool is_closed() const noexcept;\n\n  // wolf::function<void()> on_open_callback;\n\n private:\n  // copy constructor\n  w_ws_client_emc(const w_ws_client_emc &) = delete;\n  // copy operator\n  w_ws_client_emc &operator=(const w_ws_client_emc &) = delete;\n\n  static void s_on_open_callback(_In_ void *p_ptr) noexcept;\n  static void s_on_error_callback(_In_ const char *p_error, _In_ void *p_ptr) noexcept;\n  static void s_on_message_callback(_In_ const char *p_data, _In_ int p_size,\n                                    _In_ void *p_ptr) noexcept;\n\n  w_function<void(void) noexcept> _on_open_handler;\n  // w_function<void(void) noexcept> &&_on_message_handler;\n  w_function<void(std::string) noexcept> _on_error_handler;\n  // w_function<void(void) noexcept> &&_on_close_handler;\n\n  int _id = 0;\n  bool _connected = false;\n};\n}  // namespace wolf::system::socket\n\n#endif // defined(WOLF_SYSTEM_HTTP1_WS) && defined(EMSCRIPTEN)\n"
  },
  {
    "path": "wolf/system/socket/w_ws_server.cpp",
    "content": "#if defined(WOLF_SYSTEM_HTTP_WS) && defined(WOLF_SYSTEM_SOCKET)\n\n#include \"w_ws_server.hpp\"\n\nusing w_ws_server = wolf::system::socket::w_ws_server;\nusing w_session_ws_on_data_callback = wolf::system::socket::w_session_ws_on_data_callback;\nusing w_session_on_error_callback = wolf::system::socket::w_session_on_error_callback;\nusing w_socket_options = wolf::system::socket::w_socket_options;\nusing io_context = boost::asio::io_context;\nusing w_ws_stream = wolf::system::socket::w_ws_stream;\nusing tcp = boost::asio::ip::tcp;\n\nstatic boost::asio::awaitable<void>\ns_session(_In_ const boost::asio::io_context &p_io_context,\n          _In_ w_ws_stream &&p_ws,\n          _In_ const std::string p_conn_id,\n          _In_ w_session_ws_on_data_callback p_on_data_callback,\n          _In_ w_session_on_error_callback p_on_error_callback) {\n\n  // accept the websocket handshake\n  co_await p_ws.async_accept();\n\n  w_buffer _mut_buffer = {};\n  // incoming message\n  boost::beast::flat_buffer _buffer;\n\n  while (!p_io_context.stopped()) {\n    try {\n      // This buffer will hold the incoming message\n      \n      // Read a message\n      _mut_buffer.used_bytes = co_await p_ws.async_read(_buffer);\n\n      // an extra copy just for having stable ABI\n      const auto _size = std::min(_mut_buffer.buf.size(), _mut_buffer.used_bytes);\n      std::memcpy(_mut_buffer.buf.data(),\n                  static_cast<char const *>(_buffer.cdata().data()), _size);\n\n      // call callback\n      auto _is_binary = p_ws.got_binary();\n      const auto _code = p_on_data_callback(p_conn_id, _mut_buffer, _is_binary);\n      if (_code != boost::beast::websocket::close_code::none) {\n        break;\n      }\n\n      // Echo the message back\n      if (_is_binary) {\n        p_ws.binary(true);\n      } else {\n        p_ws.text(true);\n      }\n      co_await p_ws.async_write(\n          boost::asio::buffer(_mut_buffer.buf, _mut_buffer.used_bytes));\n\n    } catch (const boost::system::system_error &p_exc) {\n      if (p_exc.code() != boost::beast::websocket::error::closed) {\n        p_on_error_callback(p_conn_id, p_exc);\n      }\n    }\n  }\n}\n\nstatic boost::asio::awaitable<void>\ns_listen(_In_ const boost::asio::io_context &p_io_context,\n         _In_ const tcp::endpoint &p_endpoint,\n         _In_ const boost::beast::websocket::stream_base::timeout &p_timeout,\n         _In_ w_socket_options &p_socket_options,\n         _In_ w_session_ws_on_data_callback p_on_data_callback,\n         _In_ w_session_on_error_callback p_on_error_callback) {\n  // create acceptor from this coroutine\n  auto _executor = co_await boost::asio::this_coro::executor;\n  auto _acceptor =\n      boost::asio::use_awaitable.as_default_on(tcp::acceptor(_executor));\n\n  // open an acceptor\n  _acceptor.open(p_endpoint.protocol());\n\n  // allow address reuse\n  _acceptor.set_option(\n      boost::asio::socket_base::reuse_address(p_socket_options.reuse_address));\n\n  // bind to the server address\n  _acceptor.bind(p_endpoint);\n\n  // start listening for connections\n  _acceptor.listen(p_socket_options.max_connections);\n\n#ifdef __clang__\n#pragma unroll\n#endif\n  while (!p_io_context.stopped()) {\n    auto _ws = w_ws_stream(co_await _acceptor.async_accept());\n    // set timeout settings for the websocket\n    _ws.set_option(p_timeout);\n    // set a decorator to change the Server of the handshake\n    _ws.set_option(boost::beast::websocket::stream_base::decorator(\n        [](boost::beast::websocket::response_type &res) {\n          res.set(boost::beast::http::field::server,\n                  std::string(BOOST_BEAST_VERSION_STRING) + \"wolf-ws-server\");\n        }));\n    const auto _conn_id = wolf::system::socket::make_connection_id();\n\n    boost::asio::co_spawn(_acceptor.get_executor(),\n                          s_session(p_io_context, std::move(_ws), _conn_id,\n                                    p_on_data_callback, p_on_error_callback));\n  }\n}\n\nboost::leaf::result<int> w_ws_server::run(\n    _In_ boost::asio::io_context &p_io_context,\n    _In_ const boost::asio::ip::tcp::endpoint &&p_endpoint,\n    _In_ const boost::beast::websocket::stream_base::timeout &p_timeout,\n    _In_ w_socket_options &&p_socket_options,\n    _In_ w_session_ws_on_data_callback p_on_data_callback,\n    _In_ w_session_on_error_callback p_on_error_callback) noexcept {\n  try {\n    // server with coroutines\n    boost::asio::co_spawn(p_io_context,\n                          s_listen(p_io_context, p_endpoint, p_timeout,\n                                   p_socket_options, std::move(p_on_data_callback),\n                                   std::move(p_on_error_callback)),\n                          boost::asio::detached);\n    return 0;\n\n  } catch (_In_ const std::exception &p_ex) {\n    return W_FAILURE(std::errc::operation_canceled,\n                     \"ws server caught an exception : \" +\n                         std::string(p_ex.what()));\n  }\n}\n\n#endif //defined(WOLF_SYSTEM_HTTP_WS) && defined(WOLF_SYSTEM_SOCKET)\n"
  },
  {
    "path": "wolf/system/socket/w_ws_server.hpp",
    "content": "#if defined(WOLF_SYSTEM_HTTP_WS) && defined(WOLF_SYSTEM_SOCKET)\n\n#pragma once\n\n#include \"w_socket_options.hpp\"\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system::socket {\nclass w_ws_server {\npublic:\n  /*\n   * @param p_io_context, the boost io context\n   * @param p_endpoint, the endpoint of the server\n   * @param p_timeout, the timeout for connection\n   * @param p_socket_options, the socket options\n   * @param p_on_data_callback, on data callback for session\n   * @param p_on_timeout_callback, on timeout callback for session\n   * @param p_on_error_callback, on error callback for session\n   * @returns void\n   */\n  W_API static boost::leaf::result<int>\n  run(_In_ boost::asio::io_context &p_io_context,\n      _In_ const boost::asio::ip::tcp::endpoint &&p_endpoint,\n      _In_ const boost::beast::websocket::stream_base::timeout &p_timeout,\n      _In_ w_socket_options &&p_socket_options,\n      _In_ w_session_ws_on_data_callback p_on_data_callback,\n      _In_ w_session_on_error_callback p_on_error_callback) noexcept;\n};\n} // namespace wolf::system::socket\n\n#endif // defined(WOLF_SYSTEM_HTTP_WS) && defined(WOLF_SYSTEM_SOCKET)\n"
  },
  {
    "path": "wolf/system/test/compress.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_TEST\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#include <system/compression/w_lz4.hpp>\n#include <system/compression/w_lzma.hpp>\n\n#ifdef WOLF_SYSTEM_LZ4\n\nBOOST_AUTO_TEST_CASE(compress_lz4_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'compress_lz4_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        using lz4 = wolf::system::compression::w_lz4;\n\n        constexpr auto _mock_compression_data =\n            \"HELLO WOLF\\r\\nHELLO WOLF!*&%!HELLO WOLF!07*&%!\\r\\nThe quick \"\n            \"brown fox jumps over the lazy dog!\";\n\n        const auto _bytes = std::span(reinterpret_cast<const std::byte *>(_mock_compression_data),\n                                      strlen(_mock_compression_data));\n        const auto _bytes_len = _bytes.size();\n\n        constexpr auto _max_retry = 10;\n        BOOST_LEAF_AUTO(_compress_default, lz4::compress_default(_bytes));\n\n        BOOST_LEAF_AUTO(_decompress_default, lz4::decompress(_compress_default, _max_retry));\n        BOOST_REQUIRE(_decompress_default.size() == _bytes_len);\n\n        constexpr auto _acceleration = 1000;\n        BOOST_LEAF_AUTO(_compress_fast, lz4::compress_fast(_bytes, _acceleration));\n\n        BOOST_LEAF_AUTO(_decompress_fast, lz4::decompress(_compress_fast, _max_retry));\n        BOOST_REQUIRE(_decompress_fast.size() == _bytes_len);\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"compress_lz4_test got an error : {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] { BOOST_ERROR(\"compress_lz4_test got an error!\"); });\n\n  std::cout << \"leaving test case 'compress_lz4_test'\" << std::endl;\n}\n\n#endif // WOLF_SYSTEM_LZ4\n\n#ifdef WOLF_SYSTEM_LZMA\n\nBOOST_AUTO_TEST_CASE(compress_lzma_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'compress_lzma_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        using lzma = wolf::system::compression::w_lzma;\n\n        constexpr auto _mock_compression_data =\n            \"HELLO WOLF\\r\\nHELLO WOLF!*&%!HELLO WOLF!07*&%!\\r\\nThe quick \"\n            \"brown fox jumps over the lazy dog!\";\n\n        const auto _bytes = std::span(reinterpret_cast<const std::byte *>(_mock_compression_data),\n                                      strlen(_mock_compression_data));\n        const auto _bytes_len = _bytes.size();\n\n        BOOST_LEAF_AUTO(_compress_lzm1, lzma::compress_lzma1(_bytes, 7));\n\n        BOOST_LEAF_AUTO(_decompress_lzm1, lzma::decompress_lzma1(_compress_lzm1));\n\n        BOOST_LEAF_AUTO(_compress_lzm2, lzma::compress_lzma2(_bytes, 7));\n\n        BOOST_LEAF_AUTO(_decompress_lzm2, lzma::decompress_lzma2(_compress_lzm2));\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"compress_lzma_test got an error : {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] { BOOST_ERROR(\"compress_lzma_test got an error!\"); });\n\n  std::cout << \"leaving test case 'compress_lzma_test'\" << std::endl;\n}\n\n#endif // WOLF_SYSTEM_LZMA\n\n#endif // WOLF_TESTS"
  },
  {
    "path": "wolf/system/test/coroutine.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_TEST\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#include \"DISABLE_ANALYSIS_BEGIN\"\n#include <boost/asio.hpp>\n#include <boost/asio/experimental/awaitable_operators.hpp>\n#include \"DISABLE_ANALYSIS_END\"\n\nBOOST_AUTO_TEST_CASE(coroutine_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'coroutine_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        auto _io = boost::asio::io_context();\n        boost::asio::co_spawn(\n            _io,\n            [&]() -> boost::asio::awaitable<void> {\n              using namespace boost::asio::experimental::awaitable_operators;\n\n              auto _coro = [](_In_ bool p_abort) noexcept -> boost::asio::awaitable<std::errc> {\n                if (p_abort) {\n                  co_return std::errc::connection_aborted;\n                }\n                co_return std::errc::timed_out;\n              };\n\n              const auto _ret = co_await (_coro(true) || _coro(false));\n              BOOST_REQUIRE(std::get<0>(_ret) == std::errc::connection_aborted);\n            },\n            boost::asio::detached);\n\n        _io.run();\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"coroutine_test got an error : {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] { BOOST_ERROR(\"coroutine_test got an error!\"); });\n\n  std::cout << \"leaving test case 'coroutine_test'\" << std::endl;\n}\n\n#endif // WOLF_TESTS"
  },
  {
    "path": "wolf/system/test/gamepad.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_TEST\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#ifdef WOLF_SYSTEM_GAMEPAD_CLIENT\n\n#include <system/gamepad/w_gamepad_client.hpp>\n\nBOOST_AUTO_TEST_CASE(gamepad_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  // TODO(PooyaEimandar): write test code for gamepad\n}\n\n#endif // WOLF_SYSTEM_GAMEPAD_CLIENT\n\n#ifdef WOLF_SYSTEM_GAMEPAD_VIRTUAL\n\n#include <system/gamepad/w_gamepad_virtual_pool.hpp>\n\nBOOST_AUTO_TEST_CASE(gamepad_virtual_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'gamepad_virtual_test'\" << std::endl;\n\n  using w_gamepad_virtual_pool = wolf::system::gamepad::w_gamepad_virtual_pool;\n\n  const auto _ret = w_gamepad_virtual_pool::init();\n  BOOST_REQUIRE(_ret.has_error() == false);\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        // create 4 gamepads and destroy them at the end of their lifetime\n        BOOST_LEAF_AUTO(_gamepad_1, w_gamepad_virtual_pool::add());\n        BOOST_LEAF_AUTO(_gamepad_2, w_gamepad_virtual_pool::add());\n        BOOST_LEAF_AUTO(_gamepad_3, w_gamepad_virtual_pool::add());\n        BOOST_LEAF_AUTO(_gamepad_4, w_gamepad_virtual_pool::add());\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"gamepad_virtual_test got error : {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] { BOOST_ERROR(\"gamepad_virtual_test got an error!\"); });\n\n  w_gamepad_virtual_pool::fini();\n\n  std::cout << \"leaving test case 'gamepad_virtual_test'\" << std::endl;\n}\n\n#endif // WOLF_SYSTEM_GAMEPAD_VIRTUAL\n\n#endif // WOLF_TEST\n"
  },
  {
    "path": "wolf/system/test/gametime.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_TEST\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#include <mutex>\n#include <system/w_gametime.hpp>\n\nBOOST_AUTO_TEST_CASE(gametime_fixed_time_test) {\n  const wolf::system::w_leak_detector _detector = {};\n  using w_gametime = wolf::system::w_gametime;\n\n  std::cout << \"entering test case 'gametime_fixed_time_test'\" << std::endl;\n\n  std::once_flag _flag;\n  bool _ticked = false;\n\n  constexpr double _stop_after_secs = 3.0;\n  constexpr double _target_elapsed_secs = 1.0 / 50.0;  // 50 fps\n\n  auto _gametime = w_gametime();\n  _gametime.reset();\n  _gametime.set_fixed_time_step(true);\n  _gametime.set_target_elapsed_secs(_target_elapsed_secs);\n\n  auto _total_seconds = _gametime.get_total_secs();\n#ifdef __clang__\n#pragma unroll\n#endif\n  while (_total_seconds < _stop_after_secs) {\n    _gametime.tick([&]() { std::call_once(_flag, [&]() { _ticked = true; }); });\n\n    _total_seconds = _gametime.get_total_secs();\n  }\n\n  std::cout << \"leaving test case 'gametime_fixed_time_test'\" << std::endl;\n}\n\nBOOST_AUTO_TEST_CASE(gametime_unfixed_time_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  using w_gametime = wolf::system::w_gametime;\n\n  std::cout << \"entering test case 'gametime_unfixed_time_test'\" << std::endl;\n\n  constexpr double _stop_after_secs = 5.0;\n  constexpr double _target_elapsed_secs = 1.0 / 50.0;  // 50 fps\n\n  auto _gametime = w_gametime();\n  _gametime.reset();\n  _gametime.set_fixed_time_step(false);\n  _gametime.set_target_elapsed_secs(_target_elapsed_secs);\n\n  BOOST_REQUIRE(_gametime.get_fps() == 0);\n\n  auto _total_seconds = _gametime.get_total_secs();\n  while (_total_seconds < _stop_after_secs) {\n    _gametime.tick();\n    _total_seconds = _gametime.get_total_secs();\n  }\n\n  BOOST_REQUIRE(_gametime.get_fps() >= 30);\n\n  std::cout << \"leaving test case 'gametime_unfixed_time_test'\" << std::endl;\n}\n\n#endif // WOLF_TESTS"
  },
  {
    "path": "wolf/system/test/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<body>\n    <h1>Hello Wolf</h1>\n</body>\n<script>\n    let socket = new WebSocket(\"ws://127.0.0.1:8881\");\n    socket.onopen = function (e) {\n        alert(\"[open] connection established\");\n        alert(\"sending to server\");\n        socket.send(\"Hello Wolf from WS\");\n    };\n    socket.onmessage = function (event) {\n        console.log(`[message] data received from server: ${event.data}`);\n    };\n    socket.onclose = function (event) {\n        if (event.wasClean) {\n            alert(`[close] connection closed cleanly, code=${event.code} reason=${event.reason}`);\n        } else {\n            // e.g. server process killed or network down\n            // event.code is usually 1006 in this case\n            alert('[close] connection died');\n        }\n    };\n    socket.onerror = function (error) {\n        alert(`[error] ${error.message}`);\n    };\n</script>\n</html>"
  },
  {
    "path": "wolf/system/test/log.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_SYSTEM_LOG)\n\n#include <boost/test/included/unit_test.hpp>\n#include <random>\n#include <sstream>\n#include <system/log/w_log.hpp>\n#include <system/w_leak_detector.hpp>\n#include <system/w_process.hpp>\n#include <wolf/wolf.hpp>\n\nBOOST_AUTO_TEST_CASE(log_stress_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'log_stress_test'\" << std::endl;\n\n  using w_log = wolf::system::log::w_log;\n  using w_log_config = wolf::system::log::w_log_config;\n  using w_log_sink = wolf::system::log::w_log_sink;\n\n  auto _path = wolf::system::w_process::current_exe_path();\n  BOOST_REQUIRE(_path.has_error() == false);\n\n  const auto &_log_path = _path.value().append(\"/log/\");\n  w_log_config _config = {// create an async logger\n                          false,\n                          // enable multi-threaded feature\n                          true,\n                          // the path of log file\n                          _log_path,\n                          // the log level\n                          spdlog::level::level_enum::debug,\n                          // the flush level\n                          spdlog::level::level_enum::debug,\n  // the sinks of log\n#ifdef _MSC_VER\n                          w_log_sink::VISUAL_STUDIO | w_log_sink::CONSOLE,\n#else\n                          w_log_sink::CONSOLE,\n#endif\n                          // max file size in Mb (e.g. maximum 100 log files *\n                          // with size of 100 Mb file)\n                          100 * 1048576,\n                          // max number of files\n                          10,\n                          // rotate file on open\n                          false,\n                          // start creation time for daily log\n                          0,\n                          // start creation time for daily log\n                          0};\n\n  w_log _log(std::move(_config));\n  const auto _ret = _log.init();\n  if (_ret.has_error() == true) {\n    return;\n  }\n\n  constexpr auto _max = 5;\n  constexpr auto _min = 3;\n  std::default_random_engine _rand_engine = {};\n  std::uniform_int_distribution<size_t> _rand_gen(_min, _max);\n  const auto _max_loop = _rand_gen(_rand_engine);\n\n  std::vector<std::thread> threads;\n  for (size_t i = 0; i < _max_loop; ++i) {\n    threads.push_back(std::thread([&_log, i]() {\n      // get thread id\n      std::stringstream _sstream;\n      _sstream << std::this_thread::get_id();\n      const auto _thread_id = _sstream.str();\n\n      std::default_random_engine _rand_engine = {};\n      std::uniform_int_distribution<long long> _rand_gen(_min, _max);\n      const auto _max_delta_in_sec = _rand_gen(_rand_engine);\n\n      const auto time_1 = std::chrono::high_resolution_clock::now();\n      size_t j = 0;\n      for (;;) {\n        _log.write(\"#{} hello #{} from thread:{}\", i, j++, _thread_id);\n\n        const auto time_2 = std::chrono::high_resolution_clock::now();\n        const auto _delta =\n            std::chrono::duration_cast<std::chrono::seconds>(time_2 - time_1)\n                .count();\n        if (_delta > _max_delta_in_sec) {\n          break;\n        }\n      }\n    }));\n  }\n\n  for (auto &t : threads) {\n    t.join();\n  }\n\n  std::cout << \"leaving test case 'log_stress_test'\" << std::endl;\n}\n\n#endif  // defined(WOLF_TEST) && defined(WOLF_SYSTEM_LOG)"
  },
  {
    "path": "wolf/system/test/lua.hpp",
    "content": "#if defined(WOLF_TEST) && defined(WOLF_SYSTEM_LUA)\n\n#include <wolf.hpp>\n#include <system/w_leak_detector.hpp>\n#include <boost/test/included/unit_test.hpp>\n\n#include <system/script/w_lua.hpp>\n\nusing w_lua = wolf::system::script::w_lua;\nusing w_lib = wolf::system::script::w_lib;\n\nBOOST_AUTO_TEST_CASE(lua_run_from_buffer_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'lua_run_from_buffer_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      []() -> boost::leaf::result<void> {\n        w_lua lua{};\n        lua.open_libraries(w_lib::base);\n\n        BOOST_LEAF_AUTO(result, lua.run_from_buffer(\"a = 'hello world'\"));\n\n        BOOST_CHECK(true);\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        BOOST_ERROR(\"lua_run_from_buffer_test got an error : \" + p_trace.to_string());\n      },\n      [] { BOOST_ERROR(\"lua_run_from_buffer_test got an error\"); });\n\n  std::cout << \"leaving test case 'lua_run_from_buffer_test'\" << std::endl;\n}\n\n//BOOST_AUTO_TEST_CASE(lua_run_from_buffer_bad_script_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  std::cout << \"entering test case 'lua_run_from_buffer_bad_script_test'\" << std::endl;\n//  boost::leaf::try_handle_all(\n//      []() -> boost::leaf::result<void> {\n//        w_lua lua;\n//        lua.open_libraries(w_lib::base);\n//\n//        BOOST_LEAF_AUTO(result, lua.run_from_buffer(\"bad script\"));\n//        return {};\n//      },\n//      [](const w_trace &p_trace) { BOOST_CHECK(true); },\n//      [] {\n//        std::cout << \"lua_run_from_buffer_bad_script_test expected error from bad luad script\" << std::endl;\n//        BOOST_CHECK(true);\n//      });\n//\n//  std::cout << \"leaving test case 'lua_run_from_buffer_bad_script_test'\" << std::endl;\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_run_from_buffer_return_value_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  std::cout << \"entering test case 'lua_run_from_buffer_return_value_test'\" << std::endl;\n//\n//  boost::leaf::try_handle_all(\n//      []() -> boost::leaf::result<void> {\n//        w_lua lua;\n//        lua.open_libraries(w_lib::base);\n//\n//        auto result = lua.run_from_buffer<int, std::string>(\"return 1234, 'lua'\");\n//        if (!result) {\n//          return result.error();\n//        }\n//\n//        auto &[first, second] = result.value();\n//\n//        BOOST_REQUIRE(first == 1234);\n//        BOOST_REQUIRE(second == \"lua\");\n//\n//        return {};\n//      },\n//      [](const w_trace &p_trace) { BOOST_ERROR(\"lua_run_from_buffer_return_value_test got an error: \" + p_trace.to_string()); },\n//      [] { BOOST_ERROR(\"lua_run_from_buffer_return_value_test got an error\"); });\n//\n//  std::cout << \"leaving test case 'lua_run_from_buffer_return_value_test'\" << std::endl;\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_call_function_one_return_value_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  std::cout << \"entering test case 'lua_call_function_one_return_value_test'\" << std::endl;\n//\n//  boost::leaf::try_handle_all(\n//      []() -> boost::leaf::result<void> {\n//        w_lua lua;\n//        lua.open_libraries(w_lib::base);\n//\n//        BOOST_LEAF_CHECK(lua.run_from_buffer(\"function f (a, b, c, d) return a + b + c + d end\"));\n//        BOOST_LEAF_AUTO(result, lua.call_function<int>(\"f\", 1, 2, 3, 4));\n//        auto value = std::get<0>(result);\n//\n//        BOOST_REQUIRE(value == 10);\n//        return {};\n//      },\n//      [](const w_trace &p_trace) {\n//        BOOST_ERROR(\"lua_call_function_one_return_value_test got an error: \" + p_trace.to_string());\n//      },\n//      [] { BOOST_ERROR(\"lua_call_function_one_return_value_test got an error\"); });\n//\n//  std::cout << \"leaving test case 'lua_call_function_one_return_value_test'\" << std::endl;\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_call_function_two_return_value_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//  \n//  std::cout << \"entering test case 'lua_call_function_two_return_value_test'\" << std::endl;\n//\n//  boost::leaf::try_handle_all(\n//      []() -> boost::leaf::result<void> {\n//        w_lua lua;\n//        lua.open_libraries(w_lib::base);\n//\n//        BOOST_LEAF_CHECK(lua.run_from_buffer(\"function f (a, b, c, d) return a, b end\"));\n//        auto f = lua.call_function<int, int>(\"f\", 1, 2, 3, 4);\n//        if (!f) {\n//          return f.error();\n//        }\n//        auto &[first, second] = f.value();\n//        BOOST_REQUIRE(first == 1);\n//        BOOST_REQUIRE(second == 2);\n//\n//        return {};\n//      },\n//      [](const w_trace &p_trace) {\n//        BOOST_ERROR(\"lua_call_function_two_return_value_test got an error: \" + p_trace.to_string());\n//      },\n//      [] { BOOST_ERROR(\"lua_call_function_two_return_value_test got an error\"); });\n//\n//  std::cout << \"leaving test case 'lua_call_function_two_return_value_test'\" << std::endl;\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_call_function_nonexistent_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  std::cout << \"entering test case 'lua_call_function_nonexistent_test'\" << std::endl;\n//\n//  boost::leaf::try_handle_all(\n//      []() -> boost::leaf::result<void> {\n//        w_lua lua;\n//        lua.open_libraries(w_lib::base);\n//\n//        BOOST_LEAF_AUTO(result, lua.call_function<int>(\"f\", \"some_value\"));\n//        return {};\n//      },\n//      [](const w_trace &p_trace) { BOOST_CHECK(true); },\n//      [] {\n//        std::cout\n//            << \"lua_call_function_nonexistent_test called non-existent function which returns error\"\n//            << std::endl;\n//        BOOST_CHECK(true);\n//      });\n//\n//  std::cout << \"leaving test case 'lua_call_function_nonexistent_test'\" << std::endl;\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_call_function_unmatched_types_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  std::cout << \"entering test case 'lua_call_function_unmatched_types_test'\" << std::endl;\n//\n//  boost::leaf::try_handle_all(\n//      []() -> boost::leaf::result<void> {\n//        w_lua lua;\n//        lua.open_libraries(w_lib::base);\n//\n//        BOOST_LEAF_CHECK(lua.run_from_buffer(\"function f () return 'hello world' end\"));\n//        BOOST_LEAF_AUTO(result, lua.call_function<int>(\"f\"));\n//\n//        return {};\n//      },\n//      [](const w_trace &p_trace) { BOOST_CHECK(true); },\n//      [] {\n//        std::cout\n//            << \"lua_call_function_unmatched_types_test with mismatched return types must return error\"\n//            << std::endl;\n//        BOOST_CHECK(true);\n//      });\n//\n//  std::cout << \"leaving test case 'lua_call_function_unmatched_types_test'\" << std::endl;\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_bind_to_function_lambda_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//\n//  std::cout << \"entering test case 'lua_bind_to_function_lambda_test'\" << std::endl;\n//\n//  boost::leaf::try_handle_all(\n//      []() -> boost::leaf::result<void> {\n//        w_lua lua;\n//        lua.open_libraries(w_lib::base);\n//\n//        auto lambda = []() { return 1234; };\n//        BOOST_LEAF_CHECK(lua.bind_to_function(\"cpp_function\", lambda));\n//\n//        BOOST_LEAF_AUTO(result, lua.call_function<int>(\"cpp_function\"));\n//        auto value = std::get<0>(result);\n//\n//        BOOST_REQUIRE(value == 1234);\n//        return {};\n//      },\n//      [](const w_trace &p_trace) {\n//        BOOST_ERROR(\"lua_bind_to_function_lambda_test got an error: \" + p_trace.to_string());\n//      },\n//      [] { BOOST_ERROR(\"lua_bind_to_function_lambda_test got an error\"); });\n//\n//  std::cout << \"leaving test case 'lua_bind_to_function_lambda_test'\" << std::endl;\n//}\n//\n//int free_function() {\n//  return 1234;\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_bind_to_function_free_test) {\n//  const wolf::system::w_leak_detector _detector = {};\n//  boost::leaf::try_handle_all(\n//      []() -> boost::leaf::result<void> {\n//        w_lua lua;\n//        lua.open_libraries(w_lib::base);\n//\n//        BOOST_LEAF_CHECK(lua.bind_to_function(\"cpp_function\", free_function));\n//        BOOST_LEAF_AUTO(result, lua.call_function<int>(\"cpp_function\"));\n//        auto value = std::get<0>(result);\n//\n//        BOOST_REQUIRE(value == 1234);\n//        return {};\n//      },\n//      [](const w_trace &p_trace) { BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string()); },\n//      [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n//\n//struct bind_member_function {\n//    int member() {\n//      return 1234;\n//    }\n//};\n//\n//BOOST_AUTO_TEST_CASE(lua_bind_to_function_member_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          bind_member_function var;\n//          BOOST_LEAF_CHECK(\n//              lua.bind_to_function(\"cpp_function\", &bind_member_function::member, var));\n//\n//          BOOST_LEAF_AUTO(result, lua.call_function<int>(\"cpp_function\"));\n//          auto value = std::get<0>(result);\n//\n//          BOOST_REQUIRE(value == 1234);\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string());\n//        },\n//        [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_load_file_nonexistent_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          BOOST_LEAF_CHECK(lua.load_file(\"/no_such_file.lua\"));\n//\n//          BOOST_ERROR(\"loading nonexistent files must return error\");\n//          return {};\n//        },\n//        [](const w_trace &p_trace) { BOOST_CHECK(true); }, [] { BOOST_CHECK(true); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_run_without_load_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          BOOST_LEAF_AUTO(result, lua.run());\n//\n//          BOOST_ERROR(\"running scripts without loading one must return error\");\n//          return {};\n//        },\n//        [](const w_trace &p_trace) { BOOST_CHECK(true); }, [] { BOOST_CHECK(true); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_load_run_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          BOOST_LEAF_CHECK(lua.load_from_buffer(\"a = 'hello world'\"));\n//          BOOST_LEAF_AUTO(result, lua.run());\n//\n//          BOOST_CHECK(true);\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string());\n//        },\n//        [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_load_run_file_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          std::filesystem::path file(\"./test.lua\");\n//          std::ofstream ofs(file);\n//          ofs << \"return 'hello world'\" << std::endl;\n//          ofs.close();\n//\n//          BOOST_LEAF_CHECK(lua.load_file(file));\n//          BOOST_LEAF_AUTO(result, lua.run<std::string>());\n//\n//          BOOST_REQUIRE(std::get<0>(result) == \"hello world\");\n//\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string());\n//        },\n//        [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_load_run_multiple_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          BOOST_LEAF_CHECK(lua.load_from_buffer(\"a = 'hello world'\"));\n//          BOOST_LEAF_AUTO(result1, lua.run());\n//          BOOST_LEAF_AUTO(result2, lua.run());\n//          BOOST_LEAF_AUTO(result3, lua.run());\n//\n//          BOOST_CHECK(true);\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string());\n//        },\n//        [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_load_run_return_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          BOOST_LEAF_CHECK(lua.load_from_buffer(\"return 'hello world'\"));\n//          BOOST_LEAF_AUTO(result, lua.run<std::string>());\n//          auto &value = std::get<0>(result);\n//\n//          BOOST_REQUIRE(value == \"hello world\");\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string());\n//        },\n//        [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_load_run_params_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          BOOST_LEAF_CHECK(lua.load_from_buffer(\"local a,b = ... return a,b\"));\n//\n//          auto run_result = lua.run<std::string, int>(\"lua\", 1234);\n//          if (!run_result) {\n//            return run_result.error();\n//          }\n//          auto &[first, second] = run_result.value();\n//          BOOST_REQUIRE(first == \"lua\");\n//          BOOST_REQUIRE(second == 1234);\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string());\n//        },\n//        [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n//\n//BOOST_AUTO_TEST_CASE(lua_set_get_global_vars_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          lua.open_libraries(w_lib::base);\n//\n//          BOOST_LEAF_CHECK(lua.set_global_variable(\"string_var\", \"hello world\"));\n//          BOOST_LEAF_CHECK(lua.set_global_variable(\"int_var\", 1234));\n//\n//          std::string string_var;\n//          int int_var;\n//\n//          BOOST_LEAF_CHECK(lua.get_global_variable(\"string_var\", string_var));\n//          BOOST_REQUIRE(string_var == \"hello world\");\n//\n//          BOOST_LEAF_CHECK(lua.get_global_variable(\"int_var\", int_var));\n//          BOOST_REQUIRE(int_var == 1234);\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string());\n//        },\n//        [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n\n//BOOST_AUTO_TEST_CASE(lua_get_state_test) {\n//    const wolf::system::w_leak_detector _detector = {};\n//    boost::leaf::try_handle_all(\n//        []() -> boost::leaf::result<void> {\n//          w_lua lua;\n//          BOOST_LEAF_AUTO(state, lua.get_state());\n//\n//          BOOST_CHECK(true);\n//          return {};\n//        },\n//        [](const w_trace &p_trace) {\n//          BOOST_ERROR(\"lua_test got an error: \" + p_trace.to_string());\n//        },\n//        [] { BOOST_ERROR(\"lua_test got an error\"); });\n//}\n\n#endif  // defined(WOLF_TEST) && defined(WOLF_SYSTEM_LUAJIT)"
  },
  {
    "path": "wolf/system/test/postgresql.hpp",
    "content": "#if defined(WOLF_TEST) && defined(WOLF_SYSTEM_POSTGRESQL)\n\n#pragma once\n\n#include <wolf.hpp>\n#include <system/w_leak_detector.hpp>\n#include <boost/test/included/unit_test.hpp>\n\n#include <system/db/w_postgresql.hpp>\n\nusing wolf::system::pgdb::w_pgdb_conection;\nusing wolf::system::pgdb::w_pgdb_execresult;\nusing wolf::system::pgdb::w_pgdb_queryresult;\nusing wolf::system::pgdb::w_pgdb_record;\n\n#define POSTGRESQL_SERVER_ADDRESS \"172.26.218.210\"\n\nBOOST_AUTO_TEST_CASE(postgresql_client_connection) {\n  // example: connect to database by url string.\n  boost::leaf::try_handle_all(\n      []() -> boost::leaf::result<void> {\n        constexpr auto conn_info_str =\n            \"postgresql://root@\" POSTGRESQL_SERVER_ADDRESS \":26257/defaultdb\";\n        auto conn = w_pgdb_conection::make(conn_info_str);\n\n        BOOST_LEAF_CHECK(conn);\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        std::cout << \"got error :\" << p_trace << std::endl;\n        BOOST_REQUIRE(false);\n      },\n      [] {\n        std::cout << \"got an error!\" << std::endl;\n        BOOST_ERROR(false);\n      });\n\n  // example: connect to database by parameter pairs.\n  boost::leaf::try_handle_all(\n      []() -> boost::leaf::result<void> {\n        auto conn = w_pgdb_conection::make(\n            std::pair{\"host\", POSTGRESQL_SERVER_ADDRESS}, std::pair{\"port\", \"26257\"},\n            std::pair{\"user\", \"root\"}, std::pair{\"password\", \"\"}, std::pair{\"dbname\", \"defaultdb\"});\n        BOOST_LEAF_CHECK(conn);\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        std::cout << \"got error :\" << p_trace << std::endl;\n        BOOST_REQUIRE(false);\n      },\n      [] {\n        std::cout << \"got an error!\" << std::endl;\n        BOOST_ERROR(false);\n      });\n}\n\nBOOST_AUTO_TEST_CASE(postgresql_client_commands_and_queries) {\n    struct User {\n      std::string name = \"\";\n      int age = 0;\n    };\n\n    constexpr auto conn_info_str =\n        \"postgresql://root@\" POSTGRESQL_SERVER_ADDRESS \":26257/defaultdb\";\n\n    const User users[] = {User{.name = \"Lizard\", .age = 12}, User{.name = \"Haxorer\", .age = 15},\n                          User{.name = \"BlueRose\", .age = 16}, User{.name = \"Cthulhu\", .age = 18}};\n\n    auto conn = w_pgdb_conection::make(conn_info_str);\n\n    BOOST_REQUIRE(conn);\n\n    // example: create a table to operate on\n    boost::leaf::try_handle_all(\n        [&]() -> boost::leaf::result<void> {\n          auto res = conn->execute(\n              \"CREATE TABLE IF NOT EXISTS Users(\"\n              \"   id SERIAL NOT NULL PRIMARY KEY,\"\n              \"   name STRING UNIQUE NOT NULL,\"\n              \"   age INT NOT NULL\"\n              \");\");\n          BOOST_LEAF_CHECK(res);\n\n          res->done();\n\n          // clean up before insertions.\n          BOOST_LEAF_CHECK(conn->execute(\"DELETE FROM Users;\"));\n\n          return {};\n        },\n        [](const w_trace &p_trace) {\n          std::cout << \"got error :\" << p_trace << std::endl;\n          BOOST_REQUIRE(false);\n        },\n        [] {\n          std::cout << \"got an error!\" << std::endl;\n          BOOST_ERROR(false);\n        });\n\n    // example: inserts\n    boost::leaf::try_handle_all(\n        [&]() -> boost::leaf::result<void> {\n          BOOST_REQUIRE(std::size(users) > 0);\n\n          for (const auto &user : users) {\n            auto res =\n                conn->execute(\"INSERT INTO Users(name, age) VALUES($1, $2);\", user.name, user.age);\n            BOOST_LEAF_ASSERT(res);\n          }\n\n          // make sure error on uniqe name is caught.\n          auto res = conn->execute(\"INSERT INTO Users(name, age) VALUES($1, $2);\", users[0].name,\n                                   users[0].age);\n          BOOST_REQUIRE(!res);\n\n          return {};\n        },\n        [](const w_trace &p_trace) {\n          std::cout << \"got error :\" << p_trace << std::endl;\n          BOOST_REQUIRE(false);\n        },\n        [] {\n          std::cout << \"got an error!\" << std::endl;\n          BOOST_ERROR(false);\n        });\n\n    // example: query, multiple rows, buffered (first fetches all then iterates)\n    boost::leaf::try_handle_all(\n        [&]() -> boost::leaf::result<void> {\n          auto res = conn->stream_query(\"SELECT name, age FROM Users;\");\n          BOOST_LEAF_CHECK(res);\n\n          BOOST_CHECK(!res->is_empty());\n\n          BOOST_REQUIRE(res->field_count() == 2);\n          BOOST_REQUIRE(res->size() == std::size(users));\n\n          BOOST_CHECK(res->field_name_at(0) == std::string(\"name\"));\n          BOOST_CHECK(res->field_name_at(1) == std::string(\"age\"));\n\n          BOOST_LEAF_CHECK(res->on_each(\n              [&, counter = 0](w_pgdb_record record) mutable -> boost::leaf::result<void> {\n                User user;\n\n                BOOST_REQUIRE(counter < std::size(users));\n\n                BOOST_LEAF_CHECK(record.scan(&user.name, &user.age));\n\n                BOOST_CHECK(user.name == users[counter].name);\n                BOOST_CHECK(user.age == users[counter].age);\n\n                ++counter;\n\n                return {};\n              }));\n\n          return {};\n        },\n        [](const w_trace &p_trace) {\n          std::cout << \"got error :\" << p_trace << std::endl;\n          BOOST_REQUIRE(false);\n        },\n        [] {\n          std::cout << \"got an error!\" << std::endl;\n          BOOST_ERROR(false);\n        });\n\n    // example: query, single result\n    boost::leaf::try_handle_all(\n        [&]() -> boost::leaf::result<void> {\n          auto res = conn->query(\"SELECT version();\");\n          BOOST_LEAF_CHECK(res);\n\n          BOOST_LEAF_CHECK(res->on_single([](w_pgdb_record record) -> boost::leaf::result<void> {\n            auto version_str = record.at(0);\n            BOOST_REQUIRE(version_str);\n\n            std::cout << \"postgresql test: database version is:\" << version_str << std::endl;\n\n            return {};\n          }));\n\n          return {};\n        },\n        [](const w_trace &p_trace) {\n          std::cout << \"got error :\" << p_trace << std::endl;\n          BOOST_REQUIRE(false);\n        },\n        [] {\n          std::cout << \"got an error!\" << std::endl;\n          BOOST_ERROR(false);\n        });\n}\n\n#endif  // WOLF_TEST\n"
  },
  {
    "path": "wolf/system/test/process.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#ifdef WOLF_TEST\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#include <system/w_process.hpp>\n\nBOOST_AUTO_TEST_CASE(process_current_path_test) {\n  const wolf::system::w_leak_detector _detector = {};\n  using w_process = wolf::system::w_process;\n\n  std::cout << \"entering test case 'process_current_path_test'\" << std::endl;\n\n  const auto _path = w_process::current_path();\n  BOOST_REQUIRE(_path.has_error() == false);\n  BOOST_REQUIRE(_path.value().empty() == false);\n\n  const auto _exe_path = w_process::current_exe_path();\n  BOOST_REQUIRE(_exe_path.has_error() == false);\n  BOOST_REQUIRE(_exe_path.value().empty() == false);\n\n  std::cout << \"leaving test case 'process_current_path_test'\" << std::endl;\n}\n\n#endif // WOLF_TEST"
  },
  {
    "path": "wolf/system/test/python.hpp",
    "content": "#if defined(WOLF_TEST) && defined(WOLF_SYSTEM_PYTHON)\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#include <system/script/w_python.hpp>\n\nusing w_python = wolf::system::python::w_python;\nstatic std::once_flag flag1, flag2;\n\nBOOST_AUTO_TEST_CASE(python_simple_script_test) {\n  constexpr auto _test_name = \"'python_simple_script_test'\";\n\n  //TODO(pooya): we have memory leak in python, so we need to check it\n\n  std::cout << \"entering test case \" << _test_name << std::endl;\n\n  boost::leaf::try_handle_all(\n      []() -> boost::leaf::result<void> {\n        auto py = w_python(PYTHON_HOME);\n\n        auto _requested_vars = std::unordered_map<std::string, std::any>();\n        BOOST_LEAF_CHECK(py.run(\"print ('Hello Wolf from Python')\", _requested_vars));\n        return {};\n      },\n      [&](const w_trace &p_trace) {\n        BOOST_ERROR(wolf::format(\"{} got an error : {}\", _test_name, p_trace.to_string()));\n      },\n      [] { BOOST_ERROR(wolf::format(\"{} got an error\", _test_name)); });\n\n  std::cout << \"leaving test case \" << _test_name << std::endl;\n}\n\nBOOST_AUTO_TEST_CASE(python_get_variable_from_script_test) {\n  constexpr auto _test_name = \"'python_get_variable_from_script_test'\";\n\n  std::cout << \"entering test case \" << _test_name << std::endl;\n\n  boost::leaf::try_handle_all(\n      []() -> boost::leaf::result<void> {\n        auto py = w_python(PYTHON_HOME);\n        auto _requested_vars = std::unordered_map<std::string, std::any>{{\"x\", (int)0}};\n        BOOST_LEAF_CHECK(py.run(\"x = 10\", _requested_vars));\n        auto x = std::any_cast<int>(_requested_vars[\"x\"]);\n        BOOST_CHECK(x == 10);\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        BOOST_ERROR(wolf::format(\"{} got an error : {}\", _test_name, p_trace.to_string()));\n      },\n      [] { BOOST_ERROR(wolf::format(\"{} got an error\", _test_name)); });\n\n  std::cout << \"leaving test case \" << _test_name << std::endl;\n}\n\n    //void apply_simple_script_from_file()\n    //{\n    //    std::cout << \"Test case #2\\n\";\n    //    python_wrapper::PythonRunner pr; // using object\n    //    pr.run_simple_script_file(\"D:/script.py\");\n    //    python_wrapper::run_simple_script_from_file(\"D:/script.py\"); // using global function\n    //    std::cout << \"Done\\n\";\n    //}\n\n    //void apply_run_function_from_script_file_and_get_result()\n    //{\n    //    std::cout << \"Test case #3\\n\";\n    //    python_wrapper::PythonRunner pr; // using object\n    //    auto val = pr.run_function_from_script_file_and_get_result<int>(\"D:/simple_math.py\", \"return_42\");\n    //    std::cout << val << '\\n';\n    //   // python_wrapper::run_simple_script_from_file(\"D:/script.py\"); // using global function\n    //    std::cout << \"Done\\n\";\n    //}\n    //void apply_call_function()\n    //{\n    //    namespace bp = boost::python;\n    //    std::cout << \"Test case #7\\n\";\n    //    std::string script =\n    //        \"def get_and_return(a, b, c):  \\n\"\n    //        \"   return a, b, c \\n\"\n    //        \"def greet():\\n\"\n    //        \"   print('Hello ...........')\";\n    //    python_wrapper::PythonRunner pr; // using object\n    //    pr.set_script(script);\n    //    auto ret = pr.call_function(\"get_and_return\", {}, 7, 2, 3.14);\n\n    //    if (bp::len(ret) != 3)\n    //        throw std::invalid_argument(\"bad\");\n    //    std::cout << bp::extract<int>(ret[0]) << '\\t'\n    //              << bp::extract<int>(ret[1]) << '\\t'\n    //              << bp::extract<double>(ret[2]) << '\\n';\n\n    //    std::cout << \"Done\\n\";\n    //}\n\n\n#endif // WOLF_TEST && WOLF_SYSTEM_PYTHON\n"
  },
  {
    "path": "wolf/system/test/signal_slot.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_SYSTEM_SIG_SLOT)\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#include <boost/signals2.hpp>\n\nBOOST_AUTO_TEST_CASE(sig_slot_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'sig_slot_test'\" << std::endl;\n\n  auto sig = boost::signals2::signal<void()>();\n  sig.connect([]() { std::cout << \"hello from slot 1\" << std::endl; });\n  sig.connect([]() { std::cout << \"hello from slot 2\" << std::endl; });\n  sig();\n\n  std::cout << \"leaving test case 'sig_slot_test'\" << std::endl;\n}\n\n#endif // defined(WOLF_TEST) && defined(WOLF_SYSYEM_SIG_SLOT)"
  },
  {
    "path": "wolf/system/test/tcp.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_SYSTEM_SOCKET)\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf.hpp>\n\n#include <system/socket/w_tcp_client.hpp>\n#include <system/socket/w_tcp_server.hpp>\n#include <system/w_timer.hpp>\n\nBOOST_AUTO_TEST_CASE(tcp_server_timeout_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'tcp_server_timeout_test'\" << std::endl;\n\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        using tcp = boost::asio::ip::tcp;\n        using w_tcp_server = wolf::system::socket::w_tcp_server;\n        using w_socket_options = wolf::system::socket::w_socket_options;\n\n        auto _io = boost::asio::io_context();\n        w_socket_options _opts = {};\n        tcp::endpoint _endpoint = {tcp::v4(), 8080};\n        auto timeout = std::chrono::milliseconds(3000);\n\n        auto t1 = std::jthread([&]() {\n          // stop server\n          std::this_thread::sleep_for(std::chrono::seconds(5));\n          _io.stop();\n        });\n\n        BOOST_LEAF_AUTO(\n            _run_res,\n            w_tcp_server::run(\n                _io, std::move(_endpoint), std::move(timeout), std::move(_opts),\n                [](const std::string &p_conn_id, w_buffer &p_mut_data) -> auto{\n                  std::cout << \"tcp server just got: /'\" << p_mut_data.to_string() << \"/'\"\n                            << \" and \" << p_mut_data.used_bytes\n                            << \" bytes from connection id: \" << p_conn_id << std::endl;\n                  return boost::system::errc::connection_aborted;\n                },\n                [](const std::string &p_conn_id, const boost::system::system_error &p_error) {\n                  std::cout << \"timeout for connection: \" << p_conn_id << \" because of \"\n                            << p_error.what() << \"error code: \" << p_error.code() << std::endl;\n                }));\n\n        _io.run();\n\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg =\n            wolf::format(\"tcp_server_timeout_test got an error : {}\", p_trace.to_string());\n        BOOST_ERROR(_msg);\n      },\n      [] { BOOST_ERROR(\"tcp_server_timeout_test got an error!\"); });\n\n  std::cout << \"leaving test case 'tcp_server_timeout_test'\" << std::endl;\n}\n\nBOOST_AUTO_TEST_CASE(tcp_client_timeout_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'tcp_client_timeout_test'\" << std::endl;\n\n  using tcp = boost::asio::ip::tcp;\n  using w_tcp_client = wolf::system::socket::w_tcp_client;\n  using w_socket_options = wolf::system::socket::w_socket_options;\n  using w_timer = wolf::system::w_timer;\n\n  auto _io = boost::asio::io_context();\n\n  w_socket_options _opts = {};\n  tcp::endpoint _endpoint = {tcp::v4(), 8000};\n\n  boost::asio::co_spawn(\n      _io,\n      [&]() -> boost::asio::awaitable<void> {\n        // create a tcp client\n        auto _client = w_tcp_client(_io);\n        // create a timer with 1 nanosecond interval\n        auto _timer = w_timer(_io);\n        _timer.expires_after(std::chrono::nanoseconds(1));\n\n        // run a coroutine\n        const auto &_ret1 = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n                                      _client.async_resolve(_endpoint));\n        // expect timeout\n        BOOST_REQUIRE(_ret1.index() == 0);\n\n        // run timer with 5 seconds interval\n        _timer.cancel();\n        _timer.expires_after(std::chrono::seconds(5));\n        const auto &_ret2 = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n                                      _client.async_resolve(\"google.com\", 443));\n        // expect resolving\n        BOOST_REQUIRE(_ret2.index() == 1);\n\n        _io.stop();\n\n        co_return;\n      },\n      boost::asio::detached);\n\n  _io.run();\n\n  std::cout << \"leaving test case 'tcp_client_timeout_test'\" << std::endl;\n}\n\nBOOST_AUTO_TEST_CASE(tcp_read_write_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'tcp_read_write_test'\" << std::endl;\n\n  using tcp = boost::asio::ip::tcp;\n  using w_tcp_client = wolf::system::socket::w_tcp_client;\n  using w_tcp_server = wolf::system::socket::w_tcp_server;\n  using w_socket_options = wolf::system::socket::w_socket_options;\n  using w_timer = wolf::system::w_timer;\n  using namespace std::chrono_literals;\n\n  auto _io = boost::asio::io_context();\n  w_socket_options _opts = {};\n  tcp::endpoint _endpoint = {tcp::v4(), 8080};\n  const auto _timeout = 10s;\n\n  boost::asio::co_spawn(\n      _io,\n      [&]() -> boost::asio::awaitable<void> {\n        // wait for server to be initialized\n        std::this_thread::sleep_for(3s);\n        // start connecting to the server\n        w_socket_options _opts = {};\n        auto _client = w_tcp_client(_io);\n        auto _timer = w_timer(_io);\n\n        _timer.expires_after(_timeout);\n        const auto &_resolve_res = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n                                             _client.async_resolve(\"127.0.0.1\", 8080));\n        // expect resolve\n        BOOST_REQUIRE(_resolve_res.index() == 1);\n\n        auto &_endpoints = std::get<1>(_resolve_res);\n        BOOST_REQUIRE(_endpoints.size() != 0);\n\n        const auto _endpoint = _endpoints.cbegin()->endpoint();\n\n        auto _conn_res = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n                                   _client.async_connect(_endpoint, _opts));\n        // expect the connection\n        BOOST_REQUIRE(_conn_res.index() == 1);\n\n        w_buffer _send_buffer(\"hello\");\n        w_buffer _recv_buffer{};\n\n        for (size_t i = 0; i < 5; i++) {\n          auto _res = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n                                _client.async_write(_send_buffer));\n          // expect the connection\n          BOOST_REQUIRE(_res.index() == 1);\n          BOOST_REQUIRE(std::get<1>(_res) == 5);\n\n          _res = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n                           _client.async_read(_recv_buffer));\n          // expect the connection\n          BOOST_REQUIRE(_res.index() == 1);\n          _recv_buffer.used_bytes = std::get<1>(_res);\n\n          BOOST_REQUIRE(_recv_buffer.used_bytes == 10);             // hello-back\n          BOOST_REQUIRE(_recv_buffer.to_string() == \"hello-back\");  // hello-back\n        }\n\n        _send_buffer.from_string(\"exit\");\n        auto _res = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n                              _client.async_write(_send_buffer));\n        // expect the connection\n        BOOST_REQUIRE(_res.index() == 1);\n        BOOST_REQUIRE(std::get<1>(_res) == 4);\n\n        _io.stop();\n\n        co_return;\n      },\n      boost::asio::detached);\n\n  // create a tcp server with 3 seconds timeout and wait for exit\n  // command from client\n  w_tcp_server::run(\n      _io, std::move(_endpoint), _timeout, std::move(_opts),\n      [](_In_ const std::string &p_conn_id, _Inout_ w_buffer &p_mut_data) -> auto{\n        // close on overflow\n        if (p_mut_data.used_bytes > 1025) {\n          return boost::system::errc::connection_aborted;\n        }\n\n        auto _reply = std::string(p_mut_data.buf.data(), p_mut_data.used_bytes);\n\n        std::cout << \"tcp server just got: \\\"\" << _reply << \"\\\" from connection id: \" << p_conn_id\n                  << std::endl;\n\n        if (_reply == \"exit\") {\n          return boost::system::errc::connection_aborted;\n        }\n        _reply += \"-back\";\n        p_mut_data.from_string(_reply);\n        return boost::system::errc::success;\n      },\n      [&](const std::string &p_conn_id, const boost::system::system_error &p_error) {\n        std::cout << \"error happened for connection: \" << p_conn_id << \" because of \"\n                  << p_error.what() << \" error code: \" << p_error.code() << std::endl;\n        _io.stop();\n      });\n\n  _io.run();\n\n  std::cout << \"leaving test case 'tcp_read_write_test'\" << std::endl;\n}\n\n#endif  // defined(WOLF_TEST) && defined(WOLF_SYSTEM_SOCKET)"
  },
  {
    "path": "wolf/system/test/trace.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST)\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\nBOOST_AUTO_TEST_CASE(trace_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'trace_test'\" << std::endl;\n\n  const auto _function_1 = []() noexcept -> boost::leaf::result<void> {\n    return W_FAILURE(std::errc::bad_message, \"error from function 1\");\n  };\n\n  const auto _function_2 = [&]() noexcept -> boost::leaf::result<void> { return _function_1(); };\n\n  // how to use w_trace\n  boost::leaf::try_handle_all(\n      [&]() -> boost::leaf::result<void> {\n        BOOST_LEAF_CHECK(_function_2());\n        std::cout << \"success!\" << std::endl;\n        BOOST_ERROR(false);\n        return {};\n      },\n      [](const w_trace &p_trace) {\n        const auto _msg = wolf::format(\"caught a test error! trace info: {}\", p_trace.to_string());\n        BOOST_WARN_MESSAGE(false, _msg);\n      },\n      [] { BOOST_ERROR(\"trace_test caught an error!\"); });\n\n  std::cout << \"leaving test case 'trace_test'\" << std::endl;\n}\n\n#endif // WOLF_TESTS"
  },
  {
    "path": "wolf/system/test/ws.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#if defined(WOLF_TEST) && defined(WOLF_SYSTEM_SOCKET) && defined(WOLF_SYSTEM_HTTP_WS)\n\n#include <boost/test/included/unit_test.hpp>\n#include <system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#include <system/socket/w_ws_client.hpp>\n#include <system/socket/w_ws_server.hpp>\n#include <system/w_timer.hpp>\n\n#include <system/socket/w_ws_client_emc.hpp>\n\nBOOST_AUTO_TEST_CASE(ws_server_timeout_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering leaving test case 'ws_server_timeout_test'\" << std::endl;\n\n  using tcp = boost::asio::ip::tcp;\n  using w_ws_server = wolf::system::socket::w_ws_server;\n  using w_socket_options = wolf::system::socket::w_socket_options;\n  using namespace std::chrono_literals;\n\n  auto _io = boost::asio::io_context();\n  w_socket_options _opts = {};\n  tcp::endpoint _endpoint = {tcp::v4(), 8881};\n\n  auto t1 = std::jthread([&]() {\n    // stop websocket server after 10\n    std::this_thread::sleep_for(10s);\n    _io.stop();\n  });\n\n  const auto _timeout = boost::beast::websocket::stream_base::timeout{// handshake_timeout\n                                                                      5s,\n                                                                      // idle_timeout\n                                                                      5s,\n                                                                      // keep_alive_pings\n                                                                      false};\n\n  w_ws_server::run(\n      _io, std::move(_endpoint), _timeout, std::move(_opts),\n      [](const std::string &p_conn_id, _Inout_ w_buffer &p_buffer,\n         _Inout_ bool &p_is_binary) -> auto{\n        std::cout << \"websocket server just got: /'\" << p_buffer.to_string() << \"/' and \"\n                  << p_buffer.used_bytes << \" bytes from connection id: \" << p_conn_id << std::endl;\n        return boost::beast::websocket::close_code::normal;\n      },\n      [](const std::string &p_conn_id, const boost::system::system_error &p_error) {\n        std::cout << \"connection just got an error: \" << p_conn_id << \" because of \"\n                  << p_error.what() << \" error code: \" << p_error.code() << std::endl;\n      });\n  _io.run();\n\n  std::cout << \"leaving test case 'ws_server_timeout_test'\" << std::endl;\n}\n\nBOOST_AUTO_TEST_CASE(ws_client_timeout_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'ws_client_timeout_test'\" << std::endl;\n\n  using tcp = boost::asio::ip::tcp;\n  using w_ws_client = wolf::system::socket::w_ws_client;\n  using w_socket_options = wolf::system::socket::w_socket_options;\n  using w_timer = wolf::system::w_timer;\n\n  auto _io = boost::asio::io_context();\n\n  tcp::endpoint _endpoint = {tcp::v4(), 8000};\n\n  boost::asio::co_spawn(\n      _io,\n      [&]() -> boost::asio::awaitable<void> {\n        // create a websocket client\n        auto _client = w_ws_client(_io);\n        // setup a timer with 1 nanosecond interval\n        auto _timer = w_timer(_io);\n        _timer.expires_after(std::chrono::nanoseconds(1));\n\n        // run a coroutine\n        const auto& _ret = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n                                    _client.async_resolve(_endpoint));\n        // expect timeout\n        BOOST_REQUIRE(_ret.index() == 0);\n\n        _io.stop();\n\n        co_return;\n      },\n      boost::asio::detached);\n\n  _io.run();\n\n  std::cout << \"leaving test case 'ws_client_timeout_test'\" << std::endl;\n}\n\n// BOOST_AUTO_TEST_CASE(ws_read_write) {\n//   const wolf::system::w_leak_detector _detector = {};\n//\n//   using tcp = boost::asio::ip::tcp;\n//   using w_ws_client = wolf::system::socket::w_ws_client;\n//   using w_ws_server = wolf::system::socket::w_ws_server;\n//   using w_socket_options = wolf::system::socket::w_socket_options;\n//   using w_timer = wolf::system::w_timer;\n//   using namespace std::chrono_literals;\n//\n//   auto _io = boost::asio::io_context();\n//   w_socket_options _opts = {};\n//   tcp::endpoint _endpoint = {tcp::v4(), 8882};\n//   const auto _timer_timeout = 10s;\n//   const auto _timeout =\n//       boost::beast::websocket::stream_base::timeout{// handshake_timeout\n//                                                     5s,\n//                                                     // idle_timeout\n//                                                     5s,\n//                                                     // keep_alive_pings\n//                                                     false};\n//   boost::asio::co_spawn(\n//       _io,\n//       [&]() -> boost::asio::awaitable<void> {\n//         // wait for server to be initialized\n//         std::this_thread::sleep_for(3s);\n//         // start connecting to the server\n//         w_socket_options _opts = {};\n//         auto _client = w_ws_client(_io);\n//         auto _timer = w_timer(_io);\n//\n//         _timer.expires_after(_timer_timeout);\n//         auto _resolve_res =\n//             co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n//                       _client.async_resolve(\"127.0.0.1\", 8882));\n//         // expect resolve\n//         BOOST_REQUIRE(_resolve_res.index() == 1);\n//\n//         auto _endpoints = std::get<1>(_resolve_res);\n//         BOOST_REQUIRE(_endpoints.size() != 0);\n//\n//         const auto _endpoint = _endpoints.cbegin()->endpoint();\n//\n//         auto _conn_res =\n//             co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n//                       _client.async_connect(_endpoint, _opts));\n//         // expect the connection\n//         BOOST_REQUIRE(_conn_res.index() == 1);\n//\n//         constexpr bool _is_binary = false;\n//         w_buffer _send_buffer(\"hello\");\n//         w_buffer _recv_buffer{};\n//\n//         for (size_t i = 0; i < 5; i++) {\n//           auto _res = co_await (_timer.async_wait(boost::asio::use_awaitable)\n//           ||\n//                                 _client.async_write(_send_buffer,\n//                                 _is_binary));\n//           // expect the connection\n//           BOOST_REQUIRE(_res.index() == 1);\n//           BOOST_REQUIRE(std::get<1>(_res) == 5);\n//\n//           _res = co_await (_timer.async_wait(boost::asio::use_awaitable) ||\n//                            _client.async_read(_recv_buffer));\n//           // expect the connection\n//           BOOST_REQUIRE(_res.index() == 1);\n//           _recv_buffer.used_bytes = std::get<1>(_res);\n//\n//           BOOST_REQUIRE(_recv_buffer.used_bytes == 10);            //\n//           hello-back BOOST_REQUIRE(_recv_buffer.to_string() == \"hello-back\");\n//           // hello-back\n//         }\n//\n//         _send_buffer.from_string(\"exit\");\n//         auto _res = co_await (_timer.async_wait(boost::asio::use_awaitable)\n//         ||\n//                               _client.async_write(_send_buffer, _is_binary));\n//         // expect the connection\n//         BOOST_REQUIRE(_res.index() == 1);\n//         BOOST_REQUIRE(std::get<1>(_res) == 4);\n//\n//         _io.stop();\n//\n//         co_return;\n//       },\n//       boost::asio::detached);\n//\n//   // create a websocket server with 3 seconds timeout and wait for the exit\n//   // process\n//   w_ws_server::run(\n//       _io, std::move(_endpoint), _timeout, std::move(_opts),\n//       [](_In_ const std::string &p_conn_id, _Inout_ w_buffer &p_buffer,\n//          _Inout_ bool &p_is_binary) -> auto{\n//         // close on overflow\n//         if (p_buffer.used_bytes > 1025) {\n//           return boost::beast::websocket::close_code::policy_error;\n//         }\n//\n//         auto _reply = std::string(p_buffer.buf.data(), p_buffer.used_bytes);\n//\n//         std::cout << \"websocket server just got: \\\"\" << _reply\n//                   << \"\\\" from connection id: \" << p_conn_id << std::endl;\n//\n//         if (_reply == \"exit\") {\n//           return boost::beast::websocket::close_code::normal;\n//         }\n//         _reply += \"-back\";\n//         p_buffer.from_string(_reply);\n//\n//         return boost::beast::websocket::close_code::none;\n//       },\n//       [&](const std::string &p_conn_id,\n//           const boost::system::system_error &p_error) {\n//         std::cout << \"error happened for connection: \" << p_conn_id\n//                   << \" because of \" << p_error.what()\n//                   << \" error code: \" << p_error.code() << std::endl;\n//         _io.stop();\n//       });\n//\n//   _io.run();\n// }\n\n#endif // defined(WOLF_TEST) && defined(WOLF_SYSTEM_SOCKET) && defined(WOLF_SYSTEM_HTTP_WS)"
  },
  {
    "path": "wolf/system/test/ws_server.sh",
    "content": "python -m http.server 8888"
  },
  {
    "path": "wolf/system/w_flags.hpp",
    "content": "#pragma once\n\n#include \"wolf.hpp\"\n\n#include <type_traits>\n\nnamespace wolf {\n\n/**\n * @brief combinable and comparable bit flags of given enum.\n *\n * Enum types, specially in C programming language, are commonly\n * used for bit flags. but in C++ an enum type requires a cast\n * and bitwise operators can't be applied to it directly.\n *\n * This class helps with avoiding repeating cast\n * and mistaken implicit numeric conversions.\n *\n * It's implicitly convertible to boolean, and supports & and | operators.\n * It's also explicitly convertible to given enum's underlying type and std::size_t.\n *\n * @tparam T  enum type to wrap.\n */\ntemplate <typename T>\n    requires std::is_enum_v<T>\nclass W_API w_flags {\npublic:\n    using enum_type = std::remove_cvref_t<T>;\n    using underlying_type = std::underlying_type_t<enum_type>;\n\n    constexpr w_flags(enum_type value) noexcept\n        : _bits(static_cast<underlying_type>(value))\n    {}\n\n    /**\n     * @brief to underlying integral type.\n     */\n    constexpr auto to_underlying() const noexcept { return _bits; }\n\n    constexpr friend w_flags operator&(w_flags lhs, w_flags rhs) noexcept\n    {\n        return w_flags(lhs._bits | rhs._bits);\n    }\n\n    constexpr friend w_flags operator&(w_flags lhs, enum_type rhs) noexcept\n    {\n        return w_flags(lhs._bits & static_cast<underlying_type>(rhs));\n    }\n\n    constexpr friend w_flags operator|(w_flags lhs, w_flags rhs) noexcept\n    {\n        return w_flags(lhs._bits | rhs._bits);\n    }\n\n    constexpr friend w_flags operator|(w_flags lhs, enum_type rhs) noexcept\n    {\n        return w_flags(lhs._bits | static_cast<underlying_type>(rhs));\n    }\n\n    constexpr friend bool operator==(w_flags lhs, w_flags rhs) noexcept\n    {\n        return lhs._bits == rhs._bits;\n    }\n\n    constexpr friend bool operator!=(w_flags lhs, w_flags rhs) noexcept\n    {\n        return lhs._bits != rhs._bits;\n    }\n\n    constexpr friend bool operator==(w_flags lhs, enum_type rhs) noexcept\n    {\n        return lhs._bits == static_cast<underlying_type>(rhs);\n    }\n\n    constexpr friend bool operator!=(w_flags lhs, enum_type rhs) noexcept\n    {\n        return lhs._bits != static_cast<underlying_type>(rhs);\n    }\n\n    constexpr operator bool() const noexcept\n    {\n        return bool(_bits);\n    }\n\n    constexpr explicit operator underlying_type() const noexcept\n    {\n        return _bits;\n    }\n\n    constexpr explicit operator std::size_t() const noexcept\n    {\n        return std::size_t(_bits);\n    }\n\nprivate:\n    constexpr explicit w_flags(underlying_type bits) noexcept\n        : _bits(bits)\n    {}\n\n    underlying_type _bits;\n};\n\ntemplate <typename T> requires std::is_enum_v<T>\nw_flags(T&&) -> w_flags<T>;\n\n}  // namespace wolf\n\n"
  },
  {
    "path": "wolf/system/w_gametime.cpp",
    "content": "#include \"w_gametime.hpp\"\n\nusing w_gametime = wolf::system::w_gametime;\n\nvoid w_gametime::reset() noexcept {\n  this->_last_time = std::chrono::steady_clock::now();\n  this->_left_over_ticks = 0.0;\n  this->_fps = 0;\n  this->_frames_this_sec = 0;\n  this->_secs_counter = 0.0;\n}\n\ndouble w_gametime::get_elapsed_secs() const noexcept { return this->_elapsed_secs; }\n\ndouble w_gametime::get_total_secs() const noexcept { return this->_total_secs; }\n\nuint32_t w_gametime::get_frames_count() const noexcept { return this->_frames_count; }\n\nuint32_t w_gametime::get_fps() const noexcept { return this->_fps; }\n\nbool w_gametime::get_is_fixed_time_step() const noexcept { return this->_fixed_time_step; }\n\nvoid w_gametime::set_fixed_time_step(bool p_value) noexcept { this->_fixed_time_step = p_value; }\n\nvoid w_gametime::set_target_elapsed_secs(double p_value) noexcept {\n  this->_target_elapsed_secs = p_value;\n}"
  },
  {
    "path": "wolf/system/w_gametime.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <chrono>\n#include <cmath>\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system {\nconstexpr auto MAX_DELTA_TIME_IN_SECS = 60000.0;  // 60 minutes\nconstexpr auto TARGET_ELAPSED_SECS = 1.0 / 60.0;\n\nclass w_gametime {\n public:\n  // default constructor\n  W_API w_gametime() noexcept = default;\n\n  // destructor\n  W_API virtual ~w_gametime() noexcept = default;\n\n  // move constructor\n  W_API w_gametime(w_gametime &&p_src) noexcept = default;\n\n  // move assignment operator.\n  W_API w_gametime &operator=(w_gametime &&p_src) noexcept = default;\n\n  W_API void reset() noexcept;\n\n  [[nodiscard]] W_API double get_elapsed_secs() const noexcept;\n\n  [[nodiscard]] W_API double get_total_secs() const noexcept;\n\n  [[nodiscard]] W_API uint32_t get_frames_count() const noexcept;\n\n  [[nodiscard]] W_API uint32_t get_fps() const noexcept;\n\n  [[nodiscard]] W_API bool get_is_fixed_time_step() const noexcept;\n\n  W_API void set_fixed_time_step(bool p_value) noexcept;\n\n  W_API void set_target_elapsed_secs(double p_value) noexcept;\n\n  template <typename F>\n  W_API void tick(F &&p_tick_function) {\n    using namespace std::chrono;\n\n    // Query the current time.\n    const auto current_time = steady_clock::now();\n    auto delta = duration<double, std::milli>(current_time - this->_last_time).count() / 1000.000;\n\n    this->_last_time = current_time;\n    this->_secs_counter += delta;\n\n    // clamp excessively large time deltas (e.g. after paused in the debugger).\n    if (delta > MAX_DELTA_TIME_IN_SECS) {\n      delta = MAX_DELTA_TIME_IN_SECS;\n    }\n\n    const auto last_frames_count = this->_frames_count;\n    if (this->_fixed_time_step) {\n      /*\n         If the app is running very close to the target elapsed time (within\n         1/4 of a millisecond (400 microseconds)) just clamp the clock to\n         exactly match the target value. This prevents tiny and irrelevant\n         errors from accumulating over time. Without this clamping, a game that\n         requested a 60 fps fixed update, running with vsync enabled on a 59.94\n         NTSC display, would eventually accumulate enough tiny errors that it\n         would drop a frame. It is better to just round small deviations down to\n         zero to leave things running smoothly.\n      */\n      constexpr auto quarter_of_one_milli_in_sec = 0.0004;\n      if (std::abs(delta - this->_target_elapsed_secs) < quarter_of_one_milli_in_sec) {\n        delta = this->_target_elapsed_secs;\n      }\n\n      this->_left_over_ticks += delta;\n      this->_elapsed_secs = this->_target_elapsed_secs;\n\n#ifdef __clang__\n#pragma unroll\n#endif\n      while (this->_left_over_ticks >= this->_target_elapsed_secs) {\n        this->_total_secs += this->_target_elapsed_secs;\n        this->_left_over_ticks -= this->_target_elapsed_secs;\n\n        this->_frames_count++;\n        p_tick_function();\n      }\n    } else {\n      // variable timestep update logic.\n      this->_left_over_ticks = 0.0;\n      this->_total_secs += delta;\n      this->_elapsed_secs = delta;\n      this->_frames_count++;\n      p_tick_function();\n    }\n\n    // track the current framerate.\n    this->_frames_this_sec += (this->_frames_count - last_frames_count);\n\n    auto one_sec = 1.0;\n    if (this->_secs_counter >= one_sec) {\n      this->_fps = this->_frames_this_sec;\n      this->_frames_this_sec = 0;\n      this->_secs_counter = std::modf(this->_secs_counter, &one_sec);\n    }\n  }\n\n  W_API void tick() {\n    tick([] {});\n  }\n\n private:\n  // copy constructor.\n  w_gametime(const w_gametime &) = delete;\n  // copy assignment operator.\n  w_gametime &operator=(const w_gametime &) = delete;\n\n  // configuring fixed timestep mode.\n  bool _fixed_time_step = false;\n\n  double _target_elapsed_secs = {TARGET_ELAPSED_SECS};\n  double _elapsed_secs = 0.0;\n  double _total_secs = 0.0;\n  double _left_over_ticks = 0.0;\n  double _secs_counter = 0.0;\n  uint32_t _fps = 0;\n  uint32_t _frames_count = 0;\n  uint32_t _frames_this_sec = 0;\n\n  std::chrono::steady_clock::time_point _last_time = {std::chrono::steady_clock::now()};\n};\n}  // namespace wolf::system"
  },
  {
    "path": "wolf/system/w_leak_detector.cpp",
    "content": "#include \"w_leak_detector.hpp\"\n#include <iostream>\n\nusing w_leak_detector = wolf::system::w_leak_detector;\n\nw_leak_detector::w_leak_detector() noexcept\n#if defined(WIN32) && defined(_DEBUG)\n    : _mem_state()\n#endif\n{\n#if defined(WIN32) && defined(_DEBUG)\n  // take a snapshot from memory\n  _CrtMemCheckpoint(&this->_mem_state);\n#endif\n}\n\nw_leak_detector::~w_leak_detector() noexcept {\n#if defined(WIN32) && defined(_DEBUG)\n  try {\n    // take a snapshot from memory\n    _CrtMemState _diff_mem;\n    _CrtMemState _new_mem_state;\n    _CrtMemCheckpoint(&_new_mem_state);\n\n    const auto _dif = _CrtMemDifference(&_diff_mem, &this->_mem_state, &_new_mem_state);\n    if (_dif > 0) {\n      _CrtMemDumpStatistics(&_diff_mem);\n      _CrtMemDumpAllObjectsSince(&this->_mem_state);\n      _CrtDumpMemoryLeaks();\n      std::cerr << \"Detected memory leak!\\r\\n\";\n      assert(false);\n      std::terminate();\n    }\n  } catch (...) {\n  }\n#endif\n}\n"
  },
  {
    "path": "wolf/system/w_leak_detector.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#if defined(WIN32) && defined(_DEBUG)\n#define _CRTDBG_MAP_ALLOC\n#endif\n\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system {\nclass w_leak_detector {\n public:\n  // default constructor\n  W_API w_leak_detector() noexcept;\n  // destructor\n  W_API virtual ~w_leak_detector() noexcept;\n\n private:\n  // move constructor\n  w_leak_detector(w_leak_detector &&p_src) noexcept = delete;\n  // move assignment operator.\n  w_leak_detector &operator=(w_leak_detector &&p_src) noexcept = delete;\n  // copy constructor.\n  w_leak_detector(const w_leak_detector &) = delete;\n  // copy assignment operator.\n  w_leak_detector &operator=(const w_leak_detector &) = delete;\n\n#if defined(WIN32) && defined(_DEBUG)\n  _CrtMemState _mem_state;\n#endif\n};\n}  // namespace wolf::system"
  },
  {
    "path": "wolf/system/w_overloaded.hpp",
    "content": "#pragma once\n\nnamespace wolf {\n\n/**\n * @brief famous `overloaded` to combine callables (specially lambdas)\n *        into one overloaded callable.\n *\n * example:\n * ```cpp\n *  double res = std::visit(\n *      overloaded{\n *          [](long long int val) { return val * 2.0; },\n *          [](double val) { return val / 2.0; },\n *          [](const auto&) { return 0.0; }\n *      },\n *      my_variant\n *  );\n * ```\n */\ntemplate <typename ...Fs>\nstruct w_overloaded : public Fs... { using Fs::operator()...; };\n\ntemplate <typename ...Fs>\nw_overloaded(Fs&& ...) -> w_overloaded<Fs...>;\n\n/**\n * @brief discards instance of any given argument on\n *        construction as implicit conversion;\n *        useful for unhandled cases in a visit.\n *\n * @note use this type only if `const auto&` doesn't suffice;\n *       for example when you want strict matches instead of\n *       implicit conversions or mistakenly falling down into\n *       default `const auto&` case.\n *\n * @note using `[](auto&&) { ... }` wouldn't be the same as\n *       it would be the best match in an overload set,\n *       unlike `[](blackhole_t) { ... }` which is triggered due implicit conversion.\n *\n * example:\n * ```cpp\n *  double res = std::visit(\n *      overloaded{\n *          [](long long int val) { return val * 2.0; },\n *          [](double val) { return val / 2.0; },\n *          [](w_blackhole) { return 0.0; }  // any other type\n *      },\n *      my_variant\n *  );\n * ```\n */\nstruct w_blackhole {\n    template <typename ...Ts>\n    constexpr w_blackhole(Ts&& ...) noexcept { /* nothing */ }\n};\n\n}  // namespace wolf\n"
  },
  {
    "path": "wolf/system/w_process.cpp",
    "content": "#include \"w_process.hpp\"\n#include \"w_trace.hpp\"\n\n#include <fstream>\n\nusing w_process = wolf::system::w_process;\n\nboost::leaf::result<std::filesystem::path> w_process::current_path() {\n  auto _path = std::filesystem::current_path();\n  return W_SUCCESS(_path);\n}\n\nboost::leaf::result<std::filesystem::path> w_process::current_exe_path() {\n  using path = std::filesystem::path;\n\n#ifdef WIN32\n  std::array<wchar_t, W_MAX_PATH> _buffer = {};\n  std::ignore = GetModuleFileNameW(nullptr, _buffer.data(), sizeof(_buffer));\n  const auto _ret = GetLastError();\n\n  if (_ret != S_OK) {\n    return W_FAILURE(_ret, \"GetModuleFileNameW failed because:\" + get_last_win_error(_ret));\n  }\n\n  auto _path = path(_buffer.data(), path::auto_format).parent_path();\n  return W_SUCCESS(_path);\n#else\n  std::stringstream buffer;\n  buffer << std::ifstream(\"/proc/self/comm\").rdbuf();\n\n  std::string _str = buffer.str();\n  return std::filesystem::path(_str);\n#endif\n}\n\n\n\n"
  },
  {
    "path": "wolf/system/w_process.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n#pragma once\n\n#include <wolf/wolf.hpp>\n\nnamespace wolf::system {\nclass w_process {\n public:\n  // default constructor\n  W_API w_process() noexcept = default;\n  // destructor\n  W_API virtual ~w_process() noexcept = default;\n  // move constructor\n  W_API w_process(w_process &&p_src) noexcept = default;\n  // move assignment operator.\n  W_API w_process &operator=(w_process &&p_src) noexcept = default;\n\n  /**\n   * get current exe path\n   * @returns current exe path\n   */\n  W_API static boost::leaf::result<std::filesystem::path> current_path();\n\n  /**\n   * get current exe path\n   * @returns current exe path\n   */\n  W_API static boost::leaf::result<std::filesystem::path> current_exe_path();\n\n private:\n  // copy constructor.\n  w_process(const w_process &) = delete;\n  // copy assignment operator.\n  w_process &operator=(const w_process &) = delete;\n};\n}  // namespace wolf::system\n"
  },
  {
    "path": "wolf/system/w_time.cpp",
    "content": "#include \"w_time.hpp\"\n\nusing w_time = wolf::system::w_time;\n\nboost::asio::awaitable<std::errc> w_time::timeout(\n    _In_ const std::chrono::steady_clock::time_point& p_deadline) noexcept {\n  using steady_timer = boost::asio::steady_timer;\n  using steady_clock = std::chrono::steady_clock;\n\n  steady_timer _timer(co_await boost::asio::this_coro::executor);\n  auto _now = steady_clock::now();\n\n#ifdef __clang__\n#pragma unroll\n#endif\n  while (p_deadline > _now) {\n    _timer.expires_at(p_deadline);\n    co_await _timer.async_wait(boost::asio::use_awaitable);\n    _now = steady_clock::now();\n  }\n  co_return std::errc::timed_out;\n}"
  },
  {
    "path": "wolf/system/w_time.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright � 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <wolf/wolf.hpp>\n#ifndef EMSCRIPTEN\n#include <boost/asio.hpp>\n#include <boost/asio/experimental/awaitable_operators.hpp>\nusing namespace boost::asio::experimental::awaitable_operators;\n#endif\n\nnamespace wolf::system {\n\n#ifndef EMSCRIPTEN\n\nclass w_timer : public boost::asio::high_resolution_timer {\n public:\n  W_API explicit w_timer(boost::asio::io_context& p_io_context)\n      : boost::asio::high_resolution_timer(p_io_context, 0) {}\n};\n\nclass w_time {\n public:\n  static boost::asio::awaitable<std::errc> timeout(\n      _In_ const std::chrono::steady_clock::time_point& p_deadline) noexcept;\n};\n\n#endif\n\n}  // namespace wolf::system"
  },
  {
    "path": "wolf/system/w_trace.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#include <boost/leaf.hpp>\n#include <gsl/gsl>\n#include <stdint.h>\n#include <deque>\n#include <iostream>\n#include <ostream>\n#include <string>\n#include <thread>\n\nclass w_trace {\n public:\n  struct stack {\n    friend std::ostream &operator<<(std::ostream &p_os, stack const &p_trace) noexcept {\n      try {\n        p_os << \"|tid:\" << p_trace.thread_id << \"|code:\" << p_trace.err_code\n             << \"|msg:\" << p_trace.err_msg << \"|src:\" << p_trace.source_file << \"(\"\n             << p_trace.source_file_line << \")\" << std::endl;\n      } catch (...) {\n      }\n      return p_os;\n    }\n    std::thread::id thread_id;\n    int64_t err_code = 0;\n    std::string err_msg;\n    std::string source_file;\n    int source_file_line = 0;\n  } W_ALIGNMENT_128;\n\n  w_trace() noexcept = default;\n\n  explicit w_trace(_In_ stack &&p_stack) noexcept {\n    try {\n      this->_stacks.emplace_front(p_stack);\n    } catch (...) {\n    }\n  }\n\n  w_trace(_In_ int64_t p_err_code, _In_ std::string p_err_msg, _In_ const char *p_source_file,\n          _In_ int p_source_file_line) noexcept {\n    try {\n      this->_stacks.emplace_front(stack{std::this_thread::get_id(), p_err_code,\n                                        std::move(p_err_msg), p_source_file, p_source_file_line});\n    } catch (...) {\n    }\n  }\n\n  w_trace(_In_ std::errc p_err_code, _In_ std::string p_err_msg, _In_ const char *p_source_file,\n          _In_ int p_source_file_line) noexcept {\n    try {\n      this->_stacks.emplace_front(stack{std::this_thread::get_id(),\n                                        gsl::narrow_cast<int64_t>(p_err_code), std::move(p_err_msg),\n                                        p_source_file, p_source_file_line});\n    } catch (...) {\n    }\n  }\n\n  void push(_In_ int64_t p_err_code, _In_ std::string p_err_msg, _In_ const char *p_source_file,\n            _In_ int p_source_file_line) noexcept {\n    try {\n      this->_stacks.emplace_front(stack{std::this_thread::get_id(), p_err_code,\n                                        std::move(p_err_msg), p_source_file, p_source_file_line});\n    } catch (...) {\n    }\n  }\n\n  std::string to_string() const noexcept {\n    std::string _result;\n    try {\n      std::stringstream ss;\n      for (const auto &_stack : this->_stacks) {\n        ss << _stack;\n      }\n      _result = ss.str();\n    } catch (...) {\n    }\n    return _result;\n  }\n\n  friend std::ostream &operator<<(std::ostream &p_os, w_trace const &p_trace) noexcept {\n    try {\n      for (const auto &index : p_trace._stacks) {\n        p_os << index;\n      }\n    } catch (...) {\n    }\n    return p_os;\n  }\n\n private:\n  std::deque<stack> _stacks = {};\n};\n\ntemplate<typename T>\n#ifndef __clang__\nrequires std::movable<T>\n#endif\nconstexpr inline boost::leaf::result<T> W_SUCCESS(T &p_param) noexcept {\n  return boost::leaf::result<T>(std::move(p_param));\n}\n\n#define W_FAILURE(p_code, p_msg) boost::leaf::new_error(w_trace(p_code, p_msg, __FILE__, __LINE__))\n\n#ifdef WIN32\n\ninline std::string get_last_win_error(_In_ DWORD p_error_id) {\n  if (p_error_id == 0) {\n    return {};\n  }\n\n  LPSTR _msg_buffer = nullptr;\n\n  // Ask Win32 to give us the string version of that message ID.\n  // The parameters we pass in, tell Win32 to create the buffer that holds the\n  // message for us (because we don't yet know how long the message string\n  // will be).\n  const auto _size = FormatMessageA(\n      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n      nullptr, p_error_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&_msg_buffer, 0, NULL);\n\n  // Copy the error message into a std::string.\n  std::string _message(_msg_buffer, _size);\n\n  // Free the Win32's string's buffer.\n  LocalFree(_msg_buffer);\n\n  return _message;\n}\n\n#endif\n"
  },
  {
    "path": "wolf/tests.cpp",
    "content": "/*\n        Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n        https://github.com/WolfEngine/WolfEngine\n*/\n\n#include <wolf/system/w_leak_detector.hpp>\n#include <wolf/wolf.hpp>\n\n#define BOOST_TEST_MODULE wolf\n#include <boost/test/included/unit_test.hpp>\n\nBOOST_AUTO_TEST_CASE(wolf_test) {\n  const wolf::system::w_leak_detector _detector = {};\n\n  std::cout << \"entering test case 'wolf_test'\" << std::endl;\n\n  const auto _wolf_version = wolf::w_init();\n  BOOST_TEST(_wolf_version.empty() == false);\n\n  std::cout << \"leaving test case 'wolf_test'\" << std::endl;\n}\n\n#pragma region system tests\n\n//#include <wolf/system/test/compress.hpp>\n//#include <wolf/system/test/coroutine.hpp>\n//#include <wolf/system/test/gamepad.hpp>\n//#include <wolf/system/test/gametime.hpp>\n//#include <wolf/system/test/log.hpp>\n////#include <wolf/system/test/postgresql.hpp>\n//#include <wolf/system/test/process.hpp>\n//#include <wolf/system/test/signal_slot.hpp>\n//#include <wolf/system/test/tcp.hpp>\n//#include <wolf/system/test/trace.hpp>\n//#include <wolf/system/test/ws.hpp>\n//#include <wolf/system/test/lua.hpp>\n//#include <wolf/system/test/python.hpp>\n\n#pragma endregion\n\n#pragma region stream tests\n\n//#include <wolf/stream/test/ffmpeg_stream.hpp>\n//#include <wolf/stream/test/rist.hpp>\n#include <wolf/stream/test/grpc.hpp>\n#include <wolf/stream/test/quic.hpp>\n\n#pragma endregion\n\n#pragma region media tests\n\n//#include <wolf/media/test/avframe.hpp>\n//#include <wolf/media/test/ffmpeg.hpp>\n//#include <wolf/media/test/image.hpp>\n//#include <wolf/media/test/openal.hpp>\n//#include <wolf/media/test/gstreamer.hpp>\n\n#pragma endregion\n\n#pragma region ml tests\n\n//#include <wolf/ml/test/w_image_processor_test.hpp>\n//#include <wolf/ml/test/w_ocr_engine_test.hpp>\n//#include <wolf/ml/test/w_referee_test.hpp>\n//#include <wolf/ml/test/w_soccer_test.hpp>\n//#include <wolf/ml/test/w_utilities_test.hpp>\n\n#pragma endregion\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/README.txt",
    "content": "FFmpeg 64-bit shared Windows build from www.gyan.dev\n\nVersion: 5.1.2-full_build-www.gyan.dev\n\nLicense: GPL v3\n\nSource Code: https://github.com/FFmpeg/FFmpeg/commit/eacfcbae69\n\nExternal Assets\nfrei0r plugins:   https://www.gyan.dev/ffmpeg/builds/ffmpeg-frei0r-plugins\nlensfun database: https://www.gyan.dev/ffmpeg/builds/ffmpeg-lensfun-db\n\nrelease-full build configuration: \n\nARCH                      x86 (generic)\nbig-endian                no\nruntime cpu detection     yes\nstandalone assembly       yes\nx86 assembler             nasm\nMMX enabled               yes\nMMXEXT enabled            yes\n3DNow! enabled            yes\n3DNow! extended enabled   yes\nSSE enabled               yes\nSSSE3 enabled             yes\nAESNI enabled             yes\nAVX enabled               yes\nAVX2 enabled              yes\nAVX-512 enabled           yes\nAVX-512ICL enabled        yes\nXOP enabled               yes\nFMA3 enabled              yes\nFMA4 enabled              yes\ni686 features enabled     yes\nCMOV is fast              yes\nEBX available             yes\nEBP available             yes\ndebug symbols             yes\nstrip symbols             yes\noptimize for size         no\noptimizations             yes\nstatic                    no\nshared                    yes\npostprocessing support    yes\nnetwork support           yes\nthreading support         pthreads\nsafe bitstream reader     yes\ntexi2html enabled         no\nperl enabled              yes\npod2man enabled           yes\nmakeinfo enabled          yes\nmakeinfo supports HTML    yes\nxmllint enabled           yes\n\nExternal libraries:\navisynth                libilbc                 libtheora\nbzlib                   libjxl                  libtwolame\nchromaprint             liblensfun              libuavs3d\nfrei0r                  libmodplug              libvidstab\ngmp                     libmp3lame              libvmaf\ngnutls                  libmysofa               libvo_amrwbenc\niconv                   libopencore_amrnb       libvorbis\nladspa                  libopencore_amrwb       libvpx\nlibaom                  libopenjpeg             libwebp\nlibaribb24              libopenmpt              libx264\nlibass                  libopus                 libx265\nlibbluray               libplacebo              libxavs2\nlibbs2b                 librav1e                libxml2\nlibcaca                 librist                 libxvid\nlibcdio                 librubberband           libzimg\nlibdav1d                libshaderc              libzmq\nlibdavs2                libshine                libzvbi\nlibflite                libsnappy               lzma\nlibfontconfig           libsoxr                 mediafoundation\nlibfreetype             libspeex                sdl2\nlibfribidi              libsrt                  zlib\nlibgme                  libssh\nlibgsm                  libsvtav1\n\nExternal libraries providing hardware acceleration:\namf                     d3d11va                 nvdec\ncuda                    dxva2                   nvenc\ncuda_llvm               ffnvcodec               opencl\ncuvid                   libmfx                  vulkan\n\nLibraries:\navcodec                 avformat                swresample\navdevice                avutil                  swscale\navfilter                postproc\n\nPrograms:\nffmpeg                  ffplay                  ffprobe\n\nEnabled decoders:\naac                     fraps                   pcm_u32le\naac_fixed               frwu                    pcm_u8\naac_latm                g2m                     pcm_vidc\naasc                    g723_1                  pcx\nac3                     g729                    pfm\nac3_fixed               gdv                     pgm\nacelp_kelvin            gem                     pgmyuv\nadpcm_4xm               gif                     pgssub\nadpcm_adx               gremlin_dpcm            pgx\nadpcm_afc               gsm                     phm\nadpcm_agm               gsm_ms                  photocd\nadpcm_aica              h261                    pictor\nadpcm_argo              h263                    pixlet\nadpcm_ct                h263i                   pjs\nadpcm_dtk               h263p                   png\nadpcm_ea                h264                    ppm\nadpcm_ea_maxis_xa       h264_cuvid              prores\nadpcm_ea_r1             h264_qsv                prosumer\nadpcm_ea_r2             hap                     psd\nadpcm_ea_r3             hca                     ptx\nadpcm_ea_xas            hcom                    qcelp\nadpcm_g722              hevc                    qdm2\nadpcm_g726              hevc_cuvid              qdmc\nadpcm_g726le            hevc_qsv                qdraw\nadpcm_ima_acorn         hnm4_video              qoi\nadpcm_ima_alp           hq_hqa                  qpeg\nadpcm_ima_amv           hqx                     qtrle\nadpcm_ima_apc           huffyuv                 r10k\nadpcm_ima_apm           hymt                    r210\nadpcm_ima_cunning       iac                     ra_144\nadpcm_ima_dat4          idcin                   ra_288\nadpcm_ima_dk3           idf                     ralf\nadpcm_ima_dk4           iff_ilbm                rasc\nadpcm_ima_ea_eacs       ilbc                    rawvideo\nadpcm_ima_ea_sead       imc                     realtext\nadpcm_ima_iss           imm4                    rl2\nadpcm_ima_moflex        imm5                    roq\nadpcm_ima_mtf           indeo2                  roq_dpcm\nadpcm_ima_oki           indeo3                  rpza\nadpcm_ima_qt            indeo4                  rscc\nadpcm_ima_rad           indeo5                  rv10\nadpcm_ima_smjpeg        interplay_acm           rv20\nadpcm_ima_ssi           interplay_dpcm          rv30\nadpcm_ima_wav           interplay_video         rv40\nadpcm_ima_ws            ipu                     s302m\nadpcm_ms                jacosub                 sami\nadpcm_mtaf              jpeg2000                sanm\nadpcm_psx               jpegls                  sbc\nadpcm_sbpro_2           jv                      scpr\nadpcm_sbpro_3           kgv1                    screenpresso\nadpcm_sbpro_4           kmvc                    sdx2_dpcm\nadpcm_swf               lagarith                sga\nadpcm_thp               libaom_av1              sgi\nadpcm_thp_le            libaribb24              sgirle\nadpcm_vima              libdav1d                sheervideo\nadpcm_xa                libdavs2                shorten\nadpcm_yamaha            libgsm                  simbiosis_imx\nadpcm_zork              libgsm_ms               sipr\nagm                     libilbc                 siren\naic                     libjxl                  smackaud\nalac                    libopencore_amrnb       smacker\nalias_pix               libopencore_amrwb       smc\nals                     libopenjpeg             smvjpeg\namrnb                   libopus                 snow\namrwb                   libspeex                sol_dpcm\namv                     libuavs3d               sonic\nanm                     libvorbis               sp5x\nansi                    libvpx_vp8              speedhq\nape                     libvpx_vp9              speex\napng                    libzvbi_teletext        srgc\naptx                    loco                    srt\naptx_hd                 lscr                    ssa\narbc                    m101                    stl\nargo                    mace3                   subrip\nass                     mace6                   subviewer\nasv1                    magicyuv                subviewer1\nasv2                    mdec                    sunrast\natrac1                  metasound               svq1\natrac3                  microdvd                svq3\natrac3al                mimic                   tak\natrac3p                 mjpeg                   targa\natrac3pal               mjpeg_cuvid             targa_y216\natrac9                  mjpeg_qsv               tdsc\naura                    mjpegb                  text\naura2                   mlp                     theora\nav1                     mmvideo                 thp\nav1_cuvid               mobiclip                tiertexseqvideo\nav1_qsv                 motionpixels            tiff\navrn                    movtext                 tmv\navrp                    mp1                     truehd\navs                     mp1float                truemotion1\navui                    mp2                     truemotion2\nayuv                    mp2float                truemotion2rt\nbethsoftvid             mp3                     truespeech\nbfi                     mp3adu                  tscc\nbink                    mp3adufloat             tscc2\nbinkaudio_dct           mp3float                tta\nbinkaudio_rdft          mp3on4                  twinvq\nbintext                 mp3on4float             txd\nbitpacked               mpc7                    ulti\nbmp                     mpc8                    utvideo\nbmv_audio               mpeg1_cuvid             v210\nbmv_video               mpeg1video              v210x\nbrender_pix             mpeg2_cuvid             v308\nc93                     mpeg2_qsv               v408\ncavs                    mpeg2video              v410\nccaption                mpeg4                   vb\ncdgraphics              mpeg4_cuvid             vble\ncdtoons                 mpegvideo               vbn\ncdxl                    mpl2                    vc1\ncfhd                    msa1                    vc1_cuvid\ncinepak                 mscc                    vc1_qsv\nclearvideo              msmpeg4v1               vc1image\ncljr                    msmpeg4v2               vcr1\ncllc                    msmpeg4v3               vmdaudio\ncomfortnoise            msnsiren                vmdvideo\ncook                    msp2                    vmnc\ncpia                    msrle                   vorbis\ncri                     mss1                    vp3\ncscd                    mss2                    vp4\ncyuv                    msvideo1                vp5\ndca                     mszh                    vp6\ndds                     mts2                    vp6a\nderf_dpcm               mv30                    vp6f\ndfa                     mvc1                    vp7\ndfpwm                   mvc2                    vp8\ndirac                   mvdv                    vp8_cuvid\ndnxhd                   mvha                    vp8_qsv\ndolby_e                 mwsc                    vp9\ndpx                     mxpeg                   vp9_cuvid\ndsd_lsbf                nellymoser              vp9_qsv\ndsd_lsbf_planar         notchlc                 vplayer\ndsd_msbf                nuv                     vqa\ndsd_msbf_planar         on2avc                  wavpack\ndsicinaudio             opus                    wcmv\ndsicinvideo             paf_audio               webp\ndss_sp                  paf_video               webvtt\ndst                     pam                     wmalossless\ndvaudio                 pbm                     wmapro\ndvbsub                  pcm_alaw                wmav1\ndvdsub                  pcm_bluray              wmav2\ndvvideo                 pcm_dvd                 wmavoice\ndxa                     pcm_f16le               wmv1\ndxtory                  pcm_f24le               wmv2\ndxv                     pcm_f32be               wmv3\neac3                    pcm_f32le               wmv3image\neacmv                   pcm_f64be               wnv1\neamad                   pcm_f64le               wrapped_avframe\neatgq                   pcm_lxf                 ws_snd1\neatgv                   pcm_mulaw               xan_dpcm\neatqi                   pcm_s16be               xan_wc3\neightbps                pcm_s16be_planar        xan_wc4\neightsvx_exp            pcm_s16le               xbin\neightsvx_fib            pcm_s16le_planar        xbm\nescape124               pcm_s24be               xface\nescape130               pcm_s24daud             xl\nevrc                    pcm_s24le               xma1\nexr                     pcm_s24le_planar        xma2\nfastaudio               pcm_s32be               xpm\nffv1                    pcm_s32le               xsub\nffvhuff                 pcm_s32le_planar        xwd\nffwavesynth             pcm_s64be               y41p\nfic                     pcm_s64le               ylc\nfits                    pcm_s8                  yop\nflac                    pcm_s8_planar           yuv4\nflashsv                 pcm_sga                 zero12v\nflashsv2                pcm_u16be               zerocodec\nflic                    pcm_u16le               zlib\nflv                     pcm_u24be               zmbv\nfmvc                    pcm_u24le\nfourxm                  pcm_u32be\n\nEnabled encoders:\na64multi                jpegls                  pcm_u24be\na64multi5               libaom_av1              pcm_u24le\naac                     libgsm                  pcm_u32be\naac_mf                  libgsm_ms               pcm_u32le\nac3                     libilbc                 pcm_u8\nac3_fixed               libjxl                  pcm_vidc\nac3_mf                  libmp3lame              pcx\nadpcm_adx               libopencore_amrnb       pfm\nadpcm_argo              libopenjpeg             pgm\nadpcm_g722              libopus                 pgmyuv\nadpcm_g726              librav1e                phm\nadpcm_g726le            libshine                png\nadpcm_ima_alp           libspeex                ppm\nadpcm_ima_amv           libsvtav1               prores\nadpcm_ima_apm           libtheora               prores_aw\nadpcm_ima_qt            libtwolame              prores_ks\nadpcm_ima_ssi           libvo_amrwbenc          qoi\nadpcm_ima_wav           libvorbis               qtrle\nadpcm_ima_ws            libvpx_vp8              r10k\nadpcm_ms                libvpx_vp9              r210\nadpcm_swf               libwebp                 ra_144\nadpcm_yamaha            libwebp_anim            rawvideo\nalac                    libx264                 roq\nalias_pix               libx264rgb              roq_dpcm\namv                     libx265                 rpza\napng                    libxavs2                rv10\naptx                    libxvid                 rv20\naptx_hd                 ljpeg                   s302m\nass                     magicyuv                sbc\nasv1                    mjpeg                   sgi\nasv2                    mjpeg_qsv               smc\navrp                    mlp                     snow\navui                    movtext                 sonic\nayuv                    mp2                     sonic_ls\nbitpacked               mp2fixed                speedhq\nbmp                     mp3_mf                  srt\ncfhd                    mpeg1video              ssa\ncinepak                 mpeg2_qsv               subrip\ncljr                    mpeg2video              sunrast\ncomfortnoise            mpeg4                   svq1\ndca                     msmpeg4v2               targa\ndfpwm                   msmpeg4v3               text\ndnxhd                   msvideo1                tiff\ndpx                     nellymoser              truehd\ndvbsub                  opus                    tta\ndvdsub                  pam                     ttml\ndvvideo                 pbm                     utvideo\neac3                    pcm_alaw                v210\nexr                     pcm_bluray              v308\nffv1                    pcm_dvd                 v408\nffvhuff                 pcm_f32be               v410\nfits                    pcm_f32le               vbn\nflac                    pcm_f64be               vc2\nflashsv                 pcm_f64le               vorbis\nflashsv2                pcm_mulaw               vp9_qsv\nflv                     pcm_s16be               wavpack\ng723_1                  pcm_s16be_planar        webvtt\ngif                     pcm_s16le               wmav1\nh261                    pcm_s16le_planar        wmav2\nh263                    pcm_s24be               wmv1\nh263p                   pcm_s24daud             wmv2\nh264_amf                pcm_s24le               wrapped_avframe\nh264_mf                 pcm_s24le_planar        xbm\nh264_nvenc              pcm_s32be               xface\nh264_qsv                pcm_s32le               xsub\nhap                     pcm_s32le_planar        xwd\nhevc_amf                pcm_s64be               y41p\nhevc_mf                 pcm_s64le               yuv4\nhevc_nvenc              pcm_s8                  zlib\nhevc_qsv                pcm_s8_planar           zmbv\nhuffyuv                 pcm_u16be\njpeg2000                pcm_u16le\n\nEnabled hwaccels:\nav1_d3d11va             hevc_nvdec              vc1_nvdec\nav1_d3d11va2            mjpeg_nvdec             vp8_nvdec\nav1_dxva2               mpeg1_nvdec             vp9_d3d11va\nav1_nvdec               mpeg2_d3d11va           vp9_d3d11va2\nh264_d3d11va            mpeg2_d3d11va2          vp9_dxva2\nh264_d3d11va2           mpeg2_dxva2             vp9_nvdec\nh264_dxva2              mpeg2_nvdec             wmv3_d3d11va\nh264_nvdec              mpeg4_nvdec             wmv3_d3d11va2\nhevc_d3d11va            vc1_d3d11va             wmv3_dxva2\nhevc_d3d11va2           vc1_d3d11va2            wmv3_nvdec\nhevc_dxva2              vc1_dxva2\n\nEnabled parsers:\naac                     dvbsub                  mpegvideo\naac_latm                dvd_nav                 opus\nac3                     dvdsub                  png\nadx                     flac                    pnm\namr                     g723_1                  qoi\nav1                     g729                    rv30\navs2                    gif                     rv40\navs3                    gsm                     sbc\nbmp                     h261                    sipr\ncavsvideo               h263                    tak\ncook                    h264                    vc1\ncri                     hevc                    vorbis\ndca                     ipu                     vp3\ndirac                   jpeg2000                vp8\ndnxhd                   mjpeg                   vp9\ndolby_e                 mlp                     webp\ndpx                     mpeg4video              xbm\ndvaudio                 mpegaudio               xma\n\nEnabled demuxers:\naa                      idcin                   pcm_f32le\naac                     idf                     pcm_f64be\naax                     iff                     pcm_f64le\nac3                     ifv                     pcm_mulaw\nace                     ilbc                    pcm_s16be\nacm                     image2                  pcm_s16le\nact                     image2_alias_pix        pcm_s24be\nadf                     image2_brender_pix      pcm_s24le\nadp                     image2pipe              pcm_s32be\nads                     image_bmp_pipe          pcm_s32le\nadx                     image_cri_pipe          pcm_s8\naea                     image_dds_pipe          pcm_u16be\nafc                     image_dpx_pipe          pcm_u16le\naiff                    image_exr_pipe          pcm_u24be\naix                     image_gem_pipe          pcm_u24le\nalp                     image_gif_pipe          pcm_u32be\namr                     image_j2k_pipe          pcm_u32le\namrnb                   image_jpeg_pipe         pcm_u8\namrwb                   image_jpegls_pipe       pcm_vidc\nanm                     image_jpegxl_pipe       pjs\napc                     image_pam_pipe          pmp\nape                     image_pbm_pipe          pp_bnk\napm                     image_pcx_pipe          pva\napng                    image_pfm_pipe          pvf\naptx                    image_pgm_pipe          qcp\naptx_hd                 image_pgmyuv_pipe       r3d\naqtitle                 image_pgx_pipe          rawvideo\nargo_asf                image_phm_pipe          realtext\nargo_brp                image_photocd_pipe      redspark\nargo_cvg                image_pictor_pipe       rl2\nasf                     image_png_pipe          rm\nasf_o                   image_ppm_pipe          roq\nass                     image_psd_pipe          rpl\nast                     image_qdraw_pipe        rsd\nau                      image_qoi_pipe          rso\nav1                     image_sgi_pipe          rtp\navi                     image_sunrast_pipe      rtsp\navisynth                image_svg_pipe          s337m\navr                     image_tiff_pipe         sami\navs                     image_vbn_pipe          sap\navs2                    image_webp_pipe         sbc\navs3                    image_xbm_pipe          sbg\nbethsoftvid             image_xpm_pipe          scc\nbfi                     image_xwd_pipe          scd\nbfstm                   imf                     sdp\nbink                    ingenient               sdr2\nbinka                   ipmovie                 sds\nbintext                 ipu                     sdx\nbit                     ircam                   segafilm\nbitpacked               iss                     ser\nbmv                     iv8                     sga\nboa                     ivf                     shorten\nbrstm                   ivr                     siff\nc93                     jacosub                 simbiosis_imx\ncaf                     jv                      sln\ncavsvideo               kux                     smacker\ncdg                     kvag                    smjpeg\ncdxl                    libgme                  smush\ncine                    libmodplug              sol\ncodec2                  libopenmpt              sox\ncodec2raw               live_flv                spdif\nconcat                  lmlm4                   srt\ndash                    loas                    stl\ndata                    lrc                     str\ndaud                    luodat                  subviewer\ndcstr                   lvf                     subviewer1\nderf                    lxf                     sup\ndfa                     m4v                     svag\ndfpwm                   matroska                svs\ndhav                    mca                     swf\ndirac                   mcc                     tak\ndnxhd                   mgsts                   tedcaptions\ndsf                     microdvd                thp\ndsicin                  mjpeg                   threedostr\ndss                     mjpeg_2000              tiertexseq\ndts                     mlp                     tmv\ndtshd                   mlv                     truehd\ndv                      mm                      tta\ndvbsub                  mmf                     tty\ndvbtxt                  mods                    txd\ndxa                     moflex                  ty\nea                      mov                     v210\nea_cdata                mp3                     v210x\neac3                    mpc                     vag\nepaf                    mpc8                    vc1\nffmetadata              mpegps                  vc1t\nfilmstrip               mpegts                  vividas\nfits                    mpegtsraw               vivo\nflac                    mpegvideo               vmd\nflic                    mpjpeg                  vobsub\nflv                     mpl2                    voc\nfourxm                  mpsub                   vpk\nfrm                     msf                     vplayer\nfsb                     msnwc_tcp               vqf\nfwse                    msp                     w64\ng722                    mtaf                    wav\ng723_1                  mtv                     wc3\ng726                    musx                    webm_dash_manifest\ng726le                  mv                      webvtt\ng729                    mvi                     wsaud\ngdv                     mxf                     wsd\ngenh                    mxg                     wsvqa\ngif                     nc                      wtv\ngsm                     nistsphere              wv\ngxf                     nsp                     wve\nh261                    nsv                     xa\nh263                    nut                     xbin\nh264                    nuv                     xmv\nhca                     obu                     xvag\nhcom                    ogg                     xwma\nhevc                    oma                     yop\nhls                     paf                     yuv4mpegpipe\nhnm                     pcm_alaw\nico                     pcm_f32be\n\nEnabled muxers:\na64                     h263                    pcm_s24be\nac3                     h264                    pcm_s24le\nadts                    hash                    pcm_s32be\nadx                     hds                     pcm_s32le\naiff                    hevc                    pcm_s8\nalp                     hls                     pcm_u16be\namr                     ico                     pcm_u16le\namv                     ilbc                    pcm_u24be\napm                     image2                  pcm_u24le\napng                    image2pipe              pcm_u32be\naptx                    ipod                    pcm_u32le\naptx_hd                 ircam                   pcm_u8\nargo_asf                ismv                    pcm_vidc\nargo_cvg                ivf                     psp\nasf                     jacosub                 rawvideo\nasf_stream              kvag                    rm\nass                     latm                    roq\nast                     lrc                     rso\nau                      m4v                     rtp\navi                     matroska                rtp_mpegts\navif                    matroska_audio          rtsp\navm2                    md5                     sap\navs2                    microdvd                sbc\navs3                    mjpeg                   scc\nbit                     mkvtimestamp_v2         segafilm\ncaf                     mlp                     segment\ncavsvideo               mmf                     smjpeg\nchromaprint             mov                     smoothstreaming\ncodec2                  mp2                     sox\ncodec2raw               mp3                     spdif\ncrc                     mp4                     spx\ndash                    mpeg1system             srt\ndata                    mpeg1vcd                stream_segment\ndaud                    mpeg1video              streamhash\ndfpwm                   mpeg2dvd                sup\ndirac                   mpeg2svcd               swf\ndnxhd                   mpeg2video              tee\ndts                     mpeg2vob                tg2\ndv                      mpegts                  tgp\neac3                    mpjpeg                  truehd\nf4v                     mxf                     tta\nffmetadata              mxf_d10                 ttml\nfifo                    mxf_opatom              uncodedframecrc\nfifo_test               null                    vc1\nfilmstrip               nut                     vc1t\nfits                    obu                     voc\nflac                    oga                     w64\nflv                     ogg                     wav\nframecrc                ogv                     webm\nframehash               oma                     webm_chunk\nframemd5                opus                    webm_dash_manifest\ng722                    pcm_alaw                webp\ng723_1                  pcm_f32be               webvtt\ng726                    pcm_f32le               wsaud\ng726le                  pcm_f64be               wtv\ngif                     pcm_f64le               wv\ngsm                     pcm_mulaw               yuv4mpegpipe\ngxf                     pcm_s16be\nh261                    pcm_s16le\n\nEnabled protocols:\nasync                   httpproxy               rtmpe\nbluray                  https                   rtmps\ncache                   icecast                 rtmpt\nconcat                  ipfs                    rtmpte\nconcatf                 ipns                    rtmpts\ncrypto                  librist                 rtp\ndata                    libsrt                  srtp\nffrtmpcrypt             libssh                  subfile\nffrtmphttp              libzmq                  tcp\nfile                    md5                     tee\nftp                     mmsh                    tls\ngopher                  mmst                    udp\ngophers                 pipe                    udplite\nhls                     prompeg\nhttp                    rtmp\n\nEnabled filters:\nabench                  decimate                pad_opencl\nabitscope               deconvolve              pal100bars\nacompressor             dedot                   pal75bars\nacontrast               deesser                 palettegen\nacopy                   deflate                 paletteuse\nacrossfade              deflicker               pan\nacrossover              deinterlace_qsv         perms\nacrusher                dejudder                perspective\nacue                    delogo                  phase\naddroi                  derain                  photosensitivity\nadeclick                deshake                 pixdesctest\nadeclip                 deshake_opencl          pixelize\nadecorrelate            despill                 pixscope\nadelay                  detelecine              pp\nadenorm                 dialoguenhance          pp7\naderivative             dilation                premultiply\nadrawgraph              dilation_opencl         prewitt\nadynamicequalizer       displace                prewitt_opencl\nadynamicsmooth          dnn_classify            program_opencl\naecho                   dnn_detect              pseudocolor\naemphasis               dnn_processing          psnr\naeval                   doubleweave             pullup\naevalsrc                drawbox                 qp\naexciter                drawgraph               random\nafade                   drawgrid                readeia608\nafftdn                  drawtext                readvitc\nafftfilt                drmeter                 realtime\nafifo                   dynaudnorm              remap\nafir                    earwax                  remap_opencl\nafirsrc                 ebur128                 removegrain\naformat                 edgedetect              removelogo\nafreqshift              elbg                    repeatfields\nafwtdn                  entropy                 replaygain\nagate                   epx                     reverse\nagraphmonitor           eq                      rgbashift\nahistogram              equalizer               rgbtestsrc\naiir                    erosion                 roberts\naintegral               erosion_opencl          roberts_opencl\nainterleave             estdif                  rotate\nalatency                exposure                rubberband\nalimiter                extractplanes           sab\nallpass                 extrastereo             scale\nallrgb                  fade                    scale2ref\nallyuv                  feedback                scale_cuda\naloop                   fftdnoiz                scale_qsv\nalphaextract            fftfilt                 scale_vulkan\nalphamerge              field                   scdet\namerge                  fieldhint               scharr\nametadata               fieldmatch              scroll\namix                    fieldorder              segment\namovie                  fifo                    select\namplify                 fillborders             selectivecolor\namultiply               find_rect               sendcmd\nanequalizer             firequalizer            separatefields\nanlmdn                  flanger                 setdar\nanlmf                   flip_vulkan             setfield\nanlms                   flite                   setparams\nanoisesrc               floodfill               setpts\nanull                   format                  setrange\nanullsink               fps                     setsar\nanullsrc                framepack               settb\napad                    framerate               shear\naperms                  framestep               showcqt\naphasemeter             freezedetect            showfreqs\naphaser                 freezeframes            showinfo\naphaseshift             frei0r                  showpalette\napsyclip                frei0r_src              showspatial\napulsator               fspp                    showspectrum\narealtime               gblur                   showspectrumpic\naresample               gblur_vulkan            showvolume\nareverse                geq                     showwaves\narnndn                  gradfun                 showwavespic\nasdr                    gradients               shuffleframes\nasegment                graphmonitor            shufflepixels\naselect                 grayworld               shuffleplanes\nasendcmd                greyedge                sidechaincompress\nasetnsamples            guided                  sidechaingate\nasetpts                 haas                    sidedata\nasetrate                haldclut                sierpinski\nasettb                  haldclutsrc             signalstats\nashowinfo               hdcd                    signature\nasidedata               headphone               silencedetect\nasoftclip               hflip                   silenceremove\naspectralstats          hflip_vulkan            sinc\nasplit                  highpass                sine\nass                     highshelf               siti\nastats                  hilbert                 smartblur\nastreamselect           histeq                  smptebars\nasubboost               histogram               smptehdbars\nasubcut                 hqdn3d                  sobel\nasupercut               hqx                     sobel_opencl\nasuperpass              hstack                  sofalizer\nasuperstop              hsvhold                 spectrumsynth\natadenoise              hsvkey                  speechnorm\natempo                  hue                     split\natilt                   huesaturation           spp\natrim                   hwdownload              sr\navectorscope            hwmap                   ssim\navgblur                 hwupload                stereo3d\navgblur_opencl          hwupload_cuda           stereotools\navgblur_vulkan          hysteresis              stereowiden\navsynctest              identity                streamselect\naxcorrelate             idet                    subtitles\nazmq                    il                      super2xsai\nbandpass                inflate                 superequalizer\nbandreject              interlace               surround\nbass                    interleave              swaprect\nbbox                    join                    swapuv\nbench                   kerndeint               tblend\nbilateral               kirsch                  telecine\nbiquad                  ladspa                  testsrc\nbitplanenoise           lagfun                  testsrc2\nblackdetect             latency                 thistogram\nblackframe              lenscorrection          threshold\nblend                   lensfun                 thumbnail\nblend_vulkan            libplacebo              thumbnail_cuda\nblockdetect             libvmaf                 tile\nblurdetect              life                    tiltshelf\nbm3d                    limitdiff               tinterlace\nboxblur                 limiter                 tlut2\nboxblur_opencl          loop                    tmedian\nbs2b                    loudnorm                tmidequalizer\nbwdif                   lowpass                 tmix\ncas                     lowshelf                tonemap\ncellauto                lumakey                 tonemap_opencl\nchannelmap              lut                     tpad\nchannelsplit            lut1d                   transpose\nchorus                  lut2                    transpose_opencl\nchromaber_vulkan        lut3d                   transpose_vulkan\nchromahold              lutrgb                  treble\nchromakey               lutyuv                  tremolo\nchromakey_cuda          mandelbrot              trim\nchromanr                maskedclamp             unpremultiply\nchromashift             maskedmax               unsharp\nciescope                maskedmerge             unsharp_opencl\ncodecview               maskedmin               untile\ncolor                   maskedthreshold         v360\ncolorbalance            maskfun                 vaguedenoiser\ncolorchannelmixer       mcompand                varblur\ncolorchart              median                  vectorscope\ncolorcontrast           mergeplanes             vflip\ncolorcorrect            mestimate               vflip_vulkan\ncolorhold               metadata                vfrdet\ncolorize                midequalizer            vibrance\ncolorkey                minterpolate            vibrato\ncolorkey_opencl         mix                     vidstabdetect\ncolorlevels             monochrome              vidstabtransform\ncolormap                morpho                  vif\ncolormatrix             movie                   vignette\ncolorspace              mpdecimate              virtualbass\ncolorspectrum           mptestsrc               vmafmotion\ncolortemperature        msad                    volume\ncompand                 multiply                volumedetect\ncompensationdelay       negate                  vpp_qsv\nconcat                  nlmeans                 vstack\nconvolution             nlmeans_opencl          w3fdif\nconvolution_opencl      nnedi                   waveform\nconvolve                noformat                weave\ncopy                    noise                   xbr\ncover_rect              normalize               xcorrelate\ncrop                    null                    xfade\ncropdetect              nullsink                xfade_opencl\ncrossfeed               nullsrc                 xmedian\ncrystalizer             openclsrc               xstack\ncue                     oscilloscope            yadif\ncurves                  overlay                 yadif_cuda\ndatascope               overlay_cuda            yaepblur\ndblur                   overlay_opencl          yuvtestsrc\ndcshift                 overlay_qsv             zmq\ndctdnoiz                overlay_vulkan          zoompan\ndeband                  owdenoise               zscale\ndeblock                 pad\n\nEnabled bsfs:\naac_adtstoasc           h264_redundant_pps      opus_metadata\nav1_frame_merge         hapqa_extract           pcm_rechunk\nav1_frame_split         hevc_metadata           pgs_frame_merge\nav1_metadata            hevc_mp4toannexb        prores_metadata\nchomp                   imx_dump_header         remove_extradata\ndca_core                mjpeg2jpeg              setts\ndump_extradata          mjpega_dump_header      text2movsub\ndv_error_marker         mov2textsub             trace_headers\neac3_core               mp3_header_decompress   truehd_core\nextract_extradata       mpeg2_metadata          vp9_metadata\nfilter_units            mpeg4_unpack_bframes    vp9_raw_reorder\nh264_metadata           noise                   vp9_superframe\nh264_mp4toannexb        null                    vp9_superframe_split\n\nEnabled indevs:\ndshow                   lavfi                   vfwcap\ngdigrab                 libcdio\n\nEnabled outdevs:\ncaca                    sdl2\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/ac3_parser.h",
    "content": "/*\n * AC-3 parser prototypes\n * Copyright (c) 2003 Fabrice Bellard\n * Copyright (c) 2003 Michael Niedermayer\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_AC3_PARSER_H\n#define AVCODEC_AC3_PARSER_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * Extract the bitstream ID and the frame size from AC-3 data.\n */\nint av_ac3_parse_header(const uint8_t *buf, size_t size,\n                        uint8_t *bitstream_id, uint16_t *frame_size);\n\n\n#endif /* AVCODEC_AC3_PARSER_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/adts_parser.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_ADTS_PARSER_H\n#define AVCODEC_ADTS_PARSER_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#define AV_AAC_ADTS_HEADER_SIZE 7\n\n/**\n * Extract the number of samples and frames from AAC data.\n * @param[in]  buf     pointer to AAC data buffer\n * @param[out] samples Pointer to where number of samples is written\n * @param[out] frames  Pointer to where number of frames is written\n * @return Returns 0 on success, error code on failure.\n */\nint av_adts_header_parse(const uint8_t *buf, uint32_t *samples,\n                         uint8_t *frames);\n\n#endif /* AVCODEC_ADTS_PARSER_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/avcodec.h",
    "content": "/*\n * copyright (c) 2001 Fabrice Bellard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_AVCODEC_H\n#define AVCODEC_AVCODEC_H\n\n/**\n * @file\n * @ingroup libavc\n * Libavcodec external API header\n */\n\n#include \"libavutil/samplefmt.h\"\n#include \"libavutil/attributes.h\"\n#include \"libavutil/avutil.h\"\n#include \"libavutil/buffer.h\"\n#include \"libavutil/dict.h\"\n#include \"libavutil/frame.h\"\n#include \"libavutil/log.h\"\n#include \"libavutil/pixfmt.h\"\n#include \"libavutil/rational.h\"\n\n#include \"codec.h\"\n#include \"codec_desc.h\"\n#include \"codec_par.h\"\n#include \"codec_id.h\"\n#include \"defs.h\"\n#include \"packet.h\"\n#include \"version_major.h\"\n#ifndef HAVE_AV_CONFIG_H\n/* When included as part of the ffmpeg build, only include the major version\n * to avoid unnecessary rebuilds. When included externally, keep including\n * the full version information. */\n#include \"version.h\"\n#endif\n\n/**\n * @defgroup libavc libavcodec\n * Encoding/Decoding Library\n *\n * @{\n *\n * @defgroup lavc_decoding Decoding\n * @{\n * @}\n *\n * @defgroup lavc_encoding Encoding\n * @{\n * @}\n *\n * @defgroup lavc_codec Codecs\n * @{\n * @defgroup lavc_codec_native Native Codecs\n * @{\n * @}\n * @defgroup lavc_codec_wrappers External library wrappers\n * @{\n * @}\n * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge\n * @{\n * @}\n * @}\n * @defgroup lavc_internal Internal\n * @{\n * @}\n * @}\n */\n\n/**\n * @ingroup libavc\n * @defgroup lavc_encdec send/receive encoding and decoding API overview\n * @{\n *\n * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/\n * avcodec_receive_packet() functions provide an encode/decode API, which\n * decouples input and output.\n *\n * The API is very similar for encoding/decoding and audio/video, and works as\n * follows:\n * - Set up and open the AVCodecContext as usual.\n * - Send valid input:\n *   - For decoding, call avcodec_send_packet() to give the decoder raw\n *     compressed data in an AVPacket.\n *   - For encoding, call avcodec_send_frame() to give the encoder an AVFrame\n *     containing uncompressed audio or video.\n *\n *   In both cases, it is recommended that AVPackets and AVFrames are\n *   refcounted, or libavcodec might have to copy the input data. (libavformat\n *   always returns refcounted AVPackets, and av_frame_get_buffer() allocates\n *   refcounted AVFrames.)\n * - Receive output in a loop. Periodically call one of the avcodec_receive_*()\n *   functions and process their output:\n *   - For decoding, call avcodec_receive_frame(). On success, it will return\n *     an AVFrame containing uncompressed audio or video data.\n *   - For encoding, call avcodec_receive_packet(). On success, it will return\n *     an AVPacket with a compressed frame.\n *\n *   Repeat this call until it returns AVERROR(EAGAIN) or an error. The\n *   AVERROR(EAGAIN) return value means that new input data is required to\n *   return new output. In this case, continue with sending input. For each\n *   input frame/packet, the codec will typically return 1 output frame/packet,\n *   but it can also be 0 or more than 1.\n *\n * At the beginning of decoding or encoding, the codec might accept multiple\n * input frames/packets without returning a frame, until its internal buffers\n * are filled. This situation is handled transparently if you follow the steps\n * outlined above.\n *\n * In theory, sending input can result in EAGAIN - this should happen only if\n * not all output was received. You can use this to structure alternative decode\n * or encode loops other than the one suggested above. For example, you could\n * try sending new input on each iteration, and try to receive output if that\n * returns EAGAIN.\n *\n * End of stream situations. These require \"flushing\" (aka draining) the codec,\n * as the codec might buffer multiple frames or packets internally for\n * performance or out of necessity (consider B-frames).\n * This is handled as follows:\n * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding)\n *   or avcodec_send_frame() (encoding) functions. This will enter draining\n *   mode.\n * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet()\n *   (encoding) in a loop until AVERROR_EOF is returned. The functions will\n *   not return AVERROR(EAGAIN), unless you forgot to enter draining mode.\n * - Before decoding can be resumed again, the codec has to be reset with\n *   avcodec_flush_buffers().\n *\n * Using the API as outlined above is highly recommended. But it is also\n * possible to call functions outside of this rigid schema. For example, you can\n * call avcodec_send_packet() repeatedly without calling\n * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed\n * until the codec's internal buffer has been filled up (which is typically of\n * size 1 per output frame, after initial input), and then reject input with\n * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to\n * read at least some output.\n *\n * Not all codecs will follow a rigid and predictable dataflow; the only\n * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on\n * one end implies that a receive/send call on the other end will succeed, or\n * at least will not fail with AVERROR(EAGAIN). In general, no codec will\n * permit unlimited buffering of input or output.\n *\n * A codec is not allowed to return AVERROR(EAGAIN) for both sending and receiving. This\n * would be an invalid state, which could put the codec user into an endless\n * loop. The API has no concept of time either: it cannot happen that trying to\n * do avcodec_send_packet() results in AVERROR(EAGAIN), but a repeated call 1 second\n * later accepts the packet (with no other receive/flush API calls involved).\n * The API is a strict state machine, and the passage of time is not supposed\n * to influence it. Some timing-dependent behavior might still be deemed\n * acceptable in certain cases. But it must never result in both send/receive\n * returning EAGAIN at the same time at any point. It must also absolutely be\n * avoided that the current state is \"unstable\" and can \"flip-flop\" between\n * the send/receive APIs allowing progress. For example, it's not allowed that\n * the codec randomly decides that it actually wants to consume a packet now\n * instead of returning a frame, after it just returned AVERROR(EAGAIN) on an\n * avcodec_send_packet() call.\n * @}\n */\n\n/**\n * @defgroup lavc_core Core functions/structures.\n * @ingroup libavc\n *\n * Basic definitions, functions for querying libavcodec capabilities,\n * allocating core structures, etc.\n * @{\n */\n\n/**\n * @ingroup lavc_encoding\n * minimum encoding buffer size\n * Used to avoid some checks during header writing.\n */\n#define AV_INPUT_BUFFER_MIN_SIZE 16384\n\n/**\n * @ingroup lavc_encoding\n */\ntypedef struct RcOverride{\n    int start_frame;\n    int end_frame;\n    int qscale; // If this is 0 then quality_factor will be used instead.\n    float quality_factor;\n} RcOverride;\n\n/* encoding support\n   These flags can be passed in AVCodecContext.flags before initialization.\n   Note: Not everything is supported yet.\n*/\n\n/**\n * Allow decoders to produce frames with data planes that are not aligned\n * to CPU requirements (e.g. due to cropping).\n */\n#define AV_CODEC_FLAG_UNALIGNED       (1 <<  0)\n/**\n * Use fixed qscale.\n */\n#define AV_CODEC_FLAG_QSCALE          (1 <<  1)\n/**\n * 4 MV per MB allowed / advanced prediction for H.263.\n */\n#define AV_CODEC_FLAG_4MV             (1 <<  2)\n/**\n * Output even those frames that might be corrupted.\n */\n#define AV_CODEC_FLAG_OUTPUT_CORRUPT  (1 <<  3)\n/**\n * Use qpel MC.\n */\n#define AV_CODEC_FLAG_QPEL            (1 <<  4)\n/**\n * Don't output frames whose parameters differ from first\n * decoded frame in stream.\n */\n#define AV_CODEC_FLAG_DROPCHANGED     (1 <<  5)\n/**\n * Use internal 2pass ratecontrol in first pass mode.\n */\n#define AV_CODEC_FLAG_PASS1           (1 <<  9)\n/**\n * Use internal 2pass ratecontrol in second pass mode.\n */\n#define AV_CODEC_FLAG_PASS2           (1 << 10)\n/**\n * loop filter.\n */\n#define AV_CODEC_FLAG_LOOP_FILTER     (1 << 11)\n/**\n * Only decode/encode grayscale.\n */\n#define AV_CODEC_FLAG_GRAY            (1 << 13)\n/**\n * error[?] variables will be set during encoding.\n */\n#define AV_CODEC_FLAG_PSNR            (1 << 15)\n#if FF_API_FLAG_TRUNCATED\n/**\n * Input bitstream might be truncated at a random location\n * instead of only at frame boundaries.\n *\n * @deprecated use codec parsers for packetizing input\n */\n#define AV_CODEC_FLAG_TRUNCATED       (1 << 16)\n#endif\n/**\n * Use interlaced DCT.\n */\n#define AV_CODEC_FLAG_INTERLACED_DCT  (1 << 18)\n/**\n * Force low delay.\n */\n#define AV_CODEC_FLAG_LOW_DELAY       (1 << 19)\n/**\n * Place global headers in extradata instead of every keyframe.\n */\n#define AV_CODEC_FLAG_GLOBAL_HEADER   (1 << 22)\n/**\n * Use only bitexact stuff (except (I)DCT).\n */\n#define AV_CODEC_FLAG_BITEXACT        (1 << 23)\n/* Fx : Flag for H.263+ extra options */\n/**\n * H.263 advanced intra coding / MPEG-4 AC prediction\n */\n#define AV_CODEC_FLAG_AC_PRED         (1 << 24)\n/**\n * interlaced motion estimation\n */\n#define AV_CODEC_FLAG_INTERLACED_ME   (1 << 29)\n#define AV_CODEC_FLAG_CLOSED_GOP      (1U << 31)\n\n/**\n * Allow non spec compliant speedup tricks.\n */\n#define AV_CODEC_FLAG2_FAST           (1 <<  0)\n/**\n * Skip bitstream encoding.\n */\n#define AV_CODEC_FLAG2_NO_OUTPUT      (1 <<  2)\n/**\n * Place global headers at every keyframe instead of in extradata.\n */\n#define AV_CODEC_FLAG2_LOCAL_HEADER   (1 <<  3)\n\n/**\n * timecode is in drop frame format. DEPRECATED!!!!\n */\n#define AV_CODEC_FLAG2_DROP_FRAME_TIMECODE (1 << 13)\n\n/**\n * Input bitstream might be truncated at a packet boundaries\n * instead of only at frame boundaries.\n */\n#define AV_CODEC_FLAG2_CHUNKS         (1 << 15)\n/**\n * Discard cropping information from SPS.\n */\n#define AV_CODEC_FLAG2_IGNORE_CROP    (1 << 16)\n\n/**\n * Show all frames before the first keyframe\n */\n#define AV_CODEC_FLAG2_SHOW_ALL       (1 << 22)\n/**\n * Export motion vectors through frame side data\n */\n#define AV_CODEC_FLAG2_EXPORT_MVS     (1 << 28)\n/**\n * Do not skip samples and export skip information as frame side data\n */\n#define AV_CODEC_FLAG2_SKIP_MANUAL    (1 << 29)\n/**\n * Do not reset ASS ReadOrder field on flush (subtitles decoding)\n */\n#define AV_CODEC_FLAG2_RO_FLUSH_NOOP  (1 << 30)\n\n/* Unsupported options :\n *              Syntax Arithmetic coding (SAC)\n *              Reference Picture Selection\n *              Independent Segment Decoding */\n/* /Fx */\n/* codec capabilities */\n\n/* Exported side data.\n   These flags can be passed in AVCodecContext.export_side_data before initialization.\n*/\n/**\n * Export motion vectors through frame side data\n */\n#define AV_CODEC_EXPORT_DATA_MVS         (1 << 0)\n/**\n * Export encoder Producer Reference Time through packet side data\n */\n#define AV_CODEC_EXPORT_DATA_PRFT        (1 << 1)\n/**\n * Decoding only.\n * Export the AVVideoEncParams structure through frame side data.\n */\n#define AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS (1 << 2)\n/**\n * Decoding only.\n * Do not apply film grain, export it instead.\n */\n#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3)\n\n/**\n * The decoder will keep a reference to the frame and may reuse it later.\n */\n#define AV_GET_BUFFER_FLAG_REF (1 << 0)\n\n/**\n * The encoder will keep a reference to the packet and may reuse it later.\n */\n#define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0)\n\nstruct AVCodecInternal;\n\n/**\n * main external API structure.\n * New fields can be added to the end with minor version bumps.\n * Removal, reordering and changes to existing fields require a major\n * version bump.\n * You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user\n * applications.\n * The name string for AVOptions options matches the associated command line\n * parameter name and can be found in libavcodec/options_table.h\n * The AVOption/command line parameter names differ in some cases from the C\n * structure field names for historic reasons or brevity.\n * sizeof(AVCodecContext) must not be used outside libav*.\n */\ntypedef struct AVCodecContext {\n    /**\n     * information on struct for av_log\n     * - set by avcodec_alloc_context3\n     */\n    const AVClass *av_class;\n    int log_level_offset;\n\n    enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */\n    const struct AVCodec  *codec;\n    enum AVCodecID     codec_id; /* see AV_CODEC_ID_xxx */\n\n    /**\n     * fourcc (LSB first, so \"ABCD\" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').\n     * This is used to work around some encoder bugs.\n     * A demuxer should set this to what is stored in the field used to identify the codec.\n     * If there are multiple such fields in a container then the demuxer should choose the one\n     * which maximizes the information about the used codec.\n     * If the codec tag field in a container is larger than 32 bits then the demuxer should\n     * remap the longer ID to 32 bits with a table or other structure. Alternatively a new\n     * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated\n     * first.\n     * - encoding: Set by user, if not then the default based on codec_id will be used.\n     * - decoding: Set by user, will be converted to uppercase by libavcodec during init.\n     */\n    unsigned int codec_tag;\n\n    void *priv_data;\n\n    /**\n     * Private context used for internal data.\n     *\n     * Unlike priv_data, this is not codec-specific. It is used in general\n     * libavcodec functions.\n     */\n    struct AVCodecInternal *internal;\n\n    /**\n     * Private data of the user, can be used to carry app specific stuff.\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     */\n    void *opaque;\n\n    /**\n     * the average bitrate\n     * - encoding: Set by user; unused for constant quantizer encoding.\n     * - decoding: Set by user, may be overwritten by libavcodec\n     *             if this info is available in the stream\n     */\n    int64_t bit_rate;\n\n    /**\n     * number of bits the bitstream is allowed to diverge from the reference.\n     *           the reference can be CBR (for CBR pass1) or VBR (for pass2)\n     * - encoding: Set by user; unused for constant quantizer encoding.\n     * - decoding: unused\n     */\n    int bit_rate_tolerance;\n\n    /**\n     * Global quality for codecs which cannot change it per frame.\n     * This should be proportional to MPEG-1/2/4 qscale.\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int global_quality;\n\n    /**\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int compression_level;\n#define FF_COMPRESSION_DEFAULT -1\n\n    /**\n     * AV_CODEC_FLAG_*.\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     */\n    int flags;\n\n    /**\n     * AV_CODEC_FLAG2_*\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     */\n    int flags2;\n\n    /**\n     * some codecs need / can use extradata like Huffman tables.\n     * MJPEG: Huffman tables\n     * rv10: additional flags\n     * MPEG-4: global headers (they can be in the bitstream or here)\n     * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger\n     * than extradata_size to avoid problems if it is read with the bitstream reader.\n     * The bytewise contents of extradata must not depend on the architecture or CPU endianness.\n     * Must be allocated with the av_malloc() family of functions.\n     * - encoding: Set/allocated/freed by libavcodec.\n     * - decoding: Set/allocated/freed by user.\n     */\n    uint8_t *extradata;\n    int extradata_size;\n\n    /**\n     * This is the fundamental unit of time (in seconds) in terms\n     * of which frame timestamps are represented. For fixed-fps content,\n     * timebase should be 1/framerate and timestamp increments should be\n     * identically 1.\n     * This often, but not always is the inverse of the frame rate or field rate\n     * for video. 1/time_base is not the average frame rate if the frame rate is not\n     * constant.\n     *\n     * Like containers, elementary streams also can store timestamps, 1/time_base\n     * is the unit in which these timestamps are specified.\n     * As example of such codec time base see ISO/IEC 14496-2:2001(E)\n     * vop_time_increment_resolution and fixed_vop_rate\n     * (fixed_vop_rate == 0 implies that it is different from the framerate)\n     *\n     * - encoding: MUST be set by user.\n     * - decoding: the use of this field for decoding is deprecated.\n     *             Use framerate instead.\n     */\n    AVRational time_base;\n\n    /**\n     * For some codecs, the time base is closer to the field rate than the frame rate.\n     * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration\n     * if no telecine is used ...\n     *\n     * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2.\n     */\n    int ticks_per_frame;\n\n    /**\n     * Codec delay.\n     *\n     * Encoding: Number of frames delay there will be from the encoder input to\n     *           the decoder output. (we assume the decoder matches the spec)\n     * Decoding: Number of frames delay in addition to what a standard decoder\n     *           as specified in the spec would produce.\n     *\n     * Video:\n     *   Number of frames the decoded output will be delayed relative to the\n     *   encoded input.\n     *\n     * Audio:\n     *   For encoding, this field is unused (see initial_padding).\n     *\n     *   For decoding, this is the number of samples the decoder needs to\n     *   output before the decoder's output is valid. When seeking, you should\n     *   start decoding this many samples prior to your desired seek point.\n     *\n     * - encoding: Set by libavcodec.\n     * - decoding: Set by libavcodec.\n     */\n    int delay;\n\n\n    /* video only */\n    /**\n     * picture width / height.\n     *\n     * @note Those fields may not match the values of the last\n     * AVFrame output by avcodec_receive_frame() due frame\n     * reordering.\n     *\n     * - encoding: MUST be set by user.\n     * - decoding: May be set by the user before opening the decoder if known e.g.\n     *             from the container. Some decoders will require the dimensions\n     *             to be set by the caller. During decoding, the decoder may\n     *             overwrite those values as required while parsing the data.\n     */\n    int width, height;\n\n    /**\n     * Bitstream width / height, may be different from width/height e.g. when\n     * the decoded frame is cropped before being output or lowres is enabled.\n     *\n     * @note Those field may not match the value of the last\n     * AVFrame output by avcodec_receive_frame() due frame\n     * reordering.\n     *\n     * - encoding: unused\n     * - decoding: May be set by the user before opening the decoder if known\n     *             e.g. from the container. During decoding, the decoder may\n     *             overwrite those values as required while parsing the data.\n     */\n    int coded_width, coded_height;\n\n    /**\n     * the number of pictures in a group of pictures, or 0 for intra_only\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int gop_size;\n\n    /**\n     * Pixel format, see AV_PIX_FMT_xxx.\n     * May be set by the demuxer if known from headers.\n     * May be overridden by the decoder if it knows better.\n     *\n     * @note This field may not match the value of the last\n     * AVFrame output by avcodec_receive_frame() due frame\n     * reordering.\n     *\n     * - encoding: Set by user.\n     * - decoding: Set by user if known, overridden by libavcodec while\n     *             parsing the data.\n     */\n    enum AVPixelFormat pix_fmt;\n\n    /**\n     * If non NULL, 'draw_horiz_band' is called by the libavcodec\n     * decoder to draw a horizontal band. It improves cache usage. Not\n     * all codecs can do that. You must check the codec capabilities\n     * beforehand.\n     * When multithreading is used, it may be called from multiple threads\n     * at the same time; threads might draw different parts of the same AVFrame,\n     * or multiple AVFrames, and there is no guarantee that slices will be drawn\n     * in order.\n     * The function is also used by hardware acceleration APIs.\n     * It is called at least once during frame decoding to pass\n     * the data needed for hardware render.\n     * In that mode instead of pixel data, AVFrame points to\n     * a structure specific to the acceleration API. The application\n     * reads the structure and can change some fields to indicate progress\n     * or mark state.\n     * - encoding: unused\n     * - decoding: Set by user.\n     * @param height the height of the slice\n     * @param y the y position of the slice\n     * @param type 1->top field, 2->bottom field, 3->frame\n     * @param offset offset into the AVFrame.data from which the slice should be read\n     */\n    void (*draw_horiz_band)(struct AVCodecContext *s,\n                            const AVFrame *src, int offset[AV_NUM_DATA_POINTERS],\n                            int y, int type, int height);\n\n    /**\n     * Callback to negotiate the pixel format. Decoding only, may be set by the\n     * caller before avcodec_open2().\n     *\n     * Called by some decoders to select the pixel format that will be used for\n     * the output frames. This is mainly used to set up hardware acceleration,\n     * then the provided format list contains the corresponding hwaccel pixel\n     * formats alongside the \"software\" one. The software pixel format may also\n     * be retrieved from \\ref sw_pix_fmt.\n     *\n     * This callback will be called when the coded frame properties (such as\n     * resolution, pixel format, etc.) change and more than one output format is\n     * supported for those new properties. If a hardware pixel format is chosen\n     * and initialization for it fails, the callback may be called again\n     * immediately.\n     *\n     * This callback may be called from different threads if the decoder is\n     * multi-threaded, but not from more than one thread simultaneously.\n     *\n     * @param fmt list of formats which may be used in the current\n     *            configuration, terminated by AV_PIX_FMT_NONE.\n     * @warning Behavior is undefined if the callback returns a value other\n     *          than one of the formats in fmt or AV_PIX_FMT_NONE.\n     * @return the chosen format or AV_PIX_FMT_NONE\n     */\n    enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt);\n\n    /**\n     * maximum number of B-frames between non-B-frames\n     * Note: The output will be delayed by max_b_frames+1 relative to the input.\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int max_b_frames;\n\n    /**\n     * qscale factor between IP and B-frames\n     * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset).\n     * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float b_quant_factor;\n\n    /**\n     * qscale offset between IP and B-frames\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float b_quant_offset;\n\n    /**\n     * Size of the frame reordering buffer in the decoder.\n     * For MPEG-2 it is 1 IPB or 0 low delay IP.\n     * - encoding: Set by libavcodec.\n     * - decoding: Set by libavcodec.\n     */\n    int has_b_frames;\n\n    /**\n     * qscale factor between P- and I-frames\n     * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset).\n     * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float i_quant_factor;\n\n    /**\n     * qscale offset between P and I-frames\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float i_quant_offset;\n\n    /**\n     * luminance masking (0-> disabled)\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float lumi_masking;\n\n    /**\n     * temporary complexity masking (0-> disabled)\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float temporal_cplx_masking;\n\n    /**\n     * spatial complexity masking (0-> disabled)\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float spatial_cplx_masking;\n\n    /**\n     * p block masking (0-> disabled)\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float p_masking;\n\n    /**\n     * darkness masking (0-> disabled)\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    float dark_masking;\n\n    /**\n     * slice count\n     * - encoding: Set by libavcodec.\n     * - decoding: Set by user (or 0).\n     */\n    int slice_count;\n\n    /**\n     * slice offsets in the frame in bytes\n     * - encoding: Set/allocated by libavcodec.\n     * - decoding: Set/allocated by user (or NULL).\n     */\n    int *slice_offset;\n\n    /**\n     * sample aspect ratio (0 if unknown)\n     * That is the width of a pixel divided by the height of the pixel.\n     * Numerator and denominator must be relatively prime and smaller than 256 for some video standards.\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n    AVRational sample_aspect_ratio;\n\n    /**\n     * motion estimation comparison function\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int me_cmp;\n    /**\n     * subpixel motion estimation comparison function\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int me_sub_cmp;\n    /**\n     * macroblock comparison function (not supported yet)\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int mb_cmp;\n    /**\n     * interlaced DCT comparison function\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int ildct_cmp;\n#define FF_CMP_SAD          0\n#define FF_CMP_SSE          1\n#define FF_CMP_SATD         2\n#define FF_CMP_DCT          3\n#define FF_CMP_PSNR         4\n#define FF_CMP_BIT          5\n#define FF_CMP_RD           6\n#define FF_CMP_ZERO         7\n#define FF_CMP_VSAD         8\n#define FF_CMP_VSSE         9\n#define FF_CMP_NSSE         10\n#define FF_CMP_W53          11\n#define FF_CMP_W97          12\n#define FF_CMP_DCTMAX       13\n#define FF_CMP_DCT264       14\n#define FF_CMP_MEDIAN_SAD   15\n#define FF_CMP_CHROMA       256\n\n    /**\n     * ME diamond size & shape\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int dia_size;\n\n    /**\n     * amount of previous MV predictors (2a+1 x 2a+1 square)\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int last_predictor_count;\n\n    /**\n     * motion estimation prepass comparison function\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int me_pre_cmp;\n\n    /**\n     * ME prepass diamond size & shape\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int pre_dia_size;\n\n    /**\n     * subpel ME quality\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int me_subpel_quality;\n\n    /**\n     * maximum motion estimation search range in subpel units\n     * If 0 then no limit.\n     *\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int me_range;\n\n    /**\n     * slice flags\n     * - encoding: unused\n     * - decoding: Set by user.\n     */\n    int slice_flags;\n#define SLICE_FLAG_CODED_ORDER    0x0001 ///< draw_horiz_band() is called in coded order instead of display\n#define SLICE_FLAG_ALLOW_FIELD    0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics)\n#define SLICE_FLAG_ALLOW_PLANE    0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1)\n\n    /**\n     * macroblock decision mode\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int mb_decision;\n#define FF_MB_DECISION_SIMPLE 0        ///< uses mb_cmp\n#define FF_MB_DECISION_BITS   1        ///< chooses the one which needs the fewest bits\n#define FF_MB_DECISION_RD     2        ///< rate distortion\n\n    /**\n     * custom intra quantization matrix\n     * Must be allocated with the av_malloc() family of functions, and will be freed in\n     * avcodec_free_context().\n     * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL.\n     * - decoding: Set/allocated/freed by libavcodec.\n     */\n    uint16_t *intra_matrix;\n\n    /**\n     * custom inter quantization matrix\n     * Must be allocated with the av_malloc() family of functions, and will be freed in\n     * avcodec_free_context().\n     * - encoding: Set/allocated by user, freed by libavcodec. Can be NULL.\n     * - decoding: Set/allocated/freed by libavcodec.\n     */\n    uint16_t *inter_matrix;\n\n    /**\n     * precision of the intra DC coefficient - 8\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec\n     */\n    int intra_dc_precision;\n\n    /**\n     * Number of macroblock rows at the top which are skipped.\n     * - encoding: unused\n     * - decoding: Set by user.\n     */\n    int skip_top;\n\n    /**\n     * Number of macroblock rows at the bottom which are skipped.\n     * - encoding: unused\n     * - decoding: Set by user.\n     */\n    int skip_bottom;\n\n    /**\n     * minimum MB Lagrange multiplier\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int mb_lmin;\n\n    /**\n     * maximum MB Lagrange multiplier\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int mb_lmax;\n\n    /**\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int bidir_refine;\n\n    /**\n     * minimum GOP size\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int keyint_min;\n\n    /**\n     * number of reference frames\n     * - encoding: Set by user.\n     * - decoding: Set by lavc.\n     */\n    int refs;\n\n    /**\n     * Note: Value depends upon the compare function used for fullpel ME.\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int mv0_threshold;\n\n    /**\n     * Chromaticity coordinates of the source primaries.\n     * - encoding: Set by user\n     * - decoding: Set by libavcodec\n     */\n    enum AVColorPrimaries color_primaries;\n\n    /**\n     * Color Transfer Characteristic.\n     * - encoding: Set by user\n     * - decoding: Set by libavcodec\n     */\n    enum AVColorTransferCharacteristic color_trc;\n\n    /**\n     * YUV colorspace type.\n     * - encoding: Set by user\n     * - decoding: Set by libavcodec\n     */\n    enum AVColorSpace colorspace;\n\n    /**\n     * MPEG vs JPEG YUV range.\n     * - encoding: Set by user\n     * - decoding: Set by libavcodec\n     */\n    enum AVColorRange color_range;\n\n    /**\n     * This defines the location of chroma samples.\n     * - encoding: Set by user\n     * - decoding: Set by libavcodec\n     */\n    enum AVChromaLocation chroma_sample_location;\n\n    /**\n     * Number of slices.\n     * Indicates number of picture subdivisions. Used for parallelized\n     * decoding.\n     * - encoding: Set by user\n     * - decoding: unused\n     */\n    int slices;\n\n    /** Field order\n     * - encoding: set by libavcodec\n     * - decoding: Set by user.\n     */\n    enum AVFieldOrder field_order;\n\n    /* audio only */\n    int sample_rate; ///< samples per second\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * number of audio channels\n     * @deprecated use ch_layout.nb_channels\n     */\n    attribute_deprecated\n    int channels;\n#endif\n\n    /**\n     * audio sample format\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n    enum AVSampleFormat sample_fmt;  ///< sample format\n\n    /* The following data should not be initialized. */\n    /**\n     * Number of samples per channel in an audio frame.\n     *\n     * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame\n     *   except the last must contain exactly frame_size samples per channel.\n     *   May be 0 when the codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE set, then the\n     *   frame size is not restricted.\n     * - decoding: may be set by some decoders to indicate constant frame size\n     */\n    int frame_size;\n\n    /**\n     * Frame counter, set by libavcodec.\n     *\n     * - decoding: total number of frames returned from the decoder so far.\n     * - encoding: total number of frames passed to the encoder so far.\n     *\n     *   @note the counter is not incremented if encoding/decoding resulted in\n     *   an error.\n     */\n    int frame_number;\n\n    /**\n     * number of bytes per packet if constant and known or 0\n     * Used by some WAV based audio codecs.\n     */\n    int block_align;\n\n    /**\n     * Audio cutoff bandwidth (0 means \"automatic\")\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int cutoff;\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * Audio channel layout.\n     * - encoding: set by user.\n     * - decoding: set by user, may be overwritten by libavcodec.\n     * @deprecated use ch_layout\n     */\n    attribute_deprecated\n    uint64_t channel_layout;\n\n    /**\n     * Request decoder to use this channel layout if it can (0 for default)\n     * - encoding: unused\n     * - decoding: Set by user.\n     * @deprecated use \"downmix\" codec private option\n     */\n    attribute_deprecated\n    uint64_t request_channel_layout;\n#endif\n\n    /**\n     * Type of service that the audio stream conveys.\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n    enum AVAudioServiceType audio_service_type;\n\n    /**\n     * desired sample format\n     * - encoding: Not used.\n     * - decoding: Set by user.\n     * Decoder will decode to this format if it can.\n     */\n    enum AVSampleFormat request_sample_fmt;\n\n    /**\n     * This callback is called at the beginning of each frame to get data\n     * buffer(s) for it. There may be one contiguous buffer for all the data or\n     * there may be a buffer per each data plane or anything in between. What\n     * this means is, you may set however many entries in buf[] you feel necessary.\n     * Each buffer must be reference-counted using the AVBuffer API (see description\n     * of buf[] below).\n     *\n     * The following fields will be set in the frame before this callback is\n     * called:\n     * - format\n     * - width, height (video only)\n     * - sample_rate, channel_layout, nb_samples (audio only)\n     * Their values may differ from the corresponding values in\n     * AVCodecContext. This callback must use the frame values, not the codec\n     * context values, to calculate the required buffer size.\n     *\n     * This callback must fill the following fields in the frame:\n     * - data[]\n     * - linesize[]\n     * - extended_data:\n     *   * if the data is planar audio with more than 8 channels, then this\n     *     callback must allocate and fill extended_data to contain all pointers\n     *     to all data planes. data[] must hold as many pointers as it can.\n     *     extended_data must be allocated with av_malloc() and will be freed in\n     *     av_frame_unref().\n     *   * otherwise extended_data must point to data\n     * - buf[] must contain one or more pointers to AVBufferRef structures. Each of\n     *   the frame's data and extended_data pointers must be contained in these. That\n     *   is, one AVBufferRef for each allocated chunk of memory, not necessarily one\n     *   AVBufferRef per data[] entry. See: av_buffer_create(), av_buffer_alloc(),\n     *   and av_buffer_ref().\n     * - extended_buf and nb_extended_buf must be allocated with av_malloc() by\n     *   this callback and filled with the extra buffers if there are more\n     *   buffers than buf[] can hold. extended_buf will be freed in\n     *   av_frame_unref().\n     *\n     * If AV_CODEC_CAP_DR1 is not set then get_buffer2() must call\n     * avcodec_default_get_buffer2() instead of providing buffers allocated by\n     * some other means.\n     *\n     * Each data plane must be aligned to the maximum required by the target\n     * CPU.\n     *\n     * @see avcodec_default_get_buffer2()\n     *\n     * Video:\n     *\n     * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused\n     * (read and/or written to if it is writable) later by libavcodec.\n     *\n     * avcodec_align_dimensions2() should be used to find the required width and\n     * height, as they normally need to be rounded up to the next multiple of 16.\n     *\n     * Some decoders do not support linesizes changing between frames.\n     *\n     * If frame multithreading is used, this callback may be called from a\n     * different thread, but not from more than one at once. Does not need to be\n     * reentrant.\n     *\n     * @see avcodec_align_dimensions2()\n     *\n     * Audio:\n     *\n     * Decoders request a buffer of a particular size by setting\n     * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may,\n     * however, utilize only part of the buffer by setting AVFrame.nb_samples\n     * to a smaller value in the output frame.\n     *\n     * As a convenience, av_samples_get_buffer_size() and\n     * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2()\n     * functions to find the required data size and to fill data pointers and\n     * linesize. In AVFrame.linesize, only linesize[0] may be set for audio\n     * since all planes must be the same size.\n     *\n     * @see av_samples_get_buffer_size(), av_samples_fill_arrays()\n     *\n     * - encoding: unused\n     * - decoding: Set by libavcodec, user can override.\n     */\n    int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags);\n\n    /* - encoding parameters */\n    float qcompress;  ///< amount of qscale change between easy & hard scenes (0.0-1.0)\n    float qblur;      ///< amount of qscale smoothing over time (0.0-1.0)\n\n    /**\n     * minimum quantizer\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int qmin;\n\n    /**\n     * maximum quantizer\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int qmax;\n\n    /**\n     * maximum quantizer difference between frames\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int max_qdiff;\n\n    /**\n     * decoder bitstream buffer size\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int rc_buffer_size;\n\n    /**\n     * ratecontrol override, see RcOverride\n     * - encoding: Allocated/set/freed by user.\n     * - decoding: unused\n     */\n    int rc_override_count;\n    RcOverride *rc_override;\n\n    /**\n     * maximum bitrate\n     * - encoding: Set by user.\n     * - decoding: Set by user, may be overwritten by libavcodec.\n     */\n    int64_t rc_max_rate;\n\n    /**\n     * minimum bitrate\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int64_t rc_min_rate;\n\n    /**\n     * Ratecontrol attempt to use, at maximum, <value> of what can be used without an underflow.\n     * - encoding: Set by user.\n     * - decoding: unused.\n     */\n    float rc_max_available_vbv_use;\n\n    /**\n     * Ratecontrol attempt to use, at least, <value> times the amount needed to prevent a vbv overflow.\n     * - encoding: Set by user.\n     * - decoding: unused.\n     */\n    float rc_min_vbv_overflow_use;\n\n    /**\n     * Number of bits which should be loaded into the rc buffer before decoding starts.\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int rc_initial_buffer_occupancy;\n\n    /**\n     * trellis RD quantization\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int trellis;\n\n    /**\n     * pass1 encoding statistics output buffer\n     * - encoding: Set by libavcodec.\n     * - decoding: unused\n     */\n    char *stats_out;\n\n    /**\n     * pass2 encoding statistics input buffer\n     * Concatenated stuff from stats_out of pass1 should be placed here.\n     * - encoding: Allocated/set/freed by user.\n     * - decoding: unused\n     */\n    char *stats_in;\n\n    /**\n     * Work around bugs in encoders which sometimes cannot be detected automatically.\n     * - encoding: Set by user\n     * - decoding: Set by user\n     */\n    int workaround_bugs;\n#define FF_BUG_AUTODETECT       1  ///< autodetection\n#define FF_BUG_XVID_ILACE       4\n#define FF_BUG_UMP4             8\n#define FF_BUG_NO_PADDING       16\n#define FF_BUG_AMV              32\n#define FF_BUG_QPEL_CHROMA      64\n#define FF_BUG_STD_QPEL         128\n#define FF_BUG_QPEL_CHROMA2     256\n#define FF_BUG_DIRECT_BLOCKSIZE 512\n#define FF_BUG_EDGE             1024\n#define FF_BUG_HPEL_CHROMA      2048\n#define FF_BUG_DC_CLIP          4096\n#define FF_BUG_MS               8192 ///< Work around various bugs in Microsoft's broken decoders.\n#define FF_BUG_TRUNCATED       16384\n#define FF_BUG_IEDGE           32768\n\n    /**\n     * strictly follow the standard (MPEG-4, ...).\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     * Setting this to STRICT or higher means the encoder and decoder will\n     * generally do stupid things, whereas setting it to unofficial or lower\n     * will mean the encoder might produce output that is not supported by all\n     * spec-compliant decoders. Decoders don't differentiate between normal,\n     * unofficial and experimental (that is, they always try to decode things\n     * when they can) unless they are explicitly asked to behave stupidly\n     * (=strictly conform to the specs)\n     */\n    int strict_std_compliance;\n#define FF_COMPLIANCE_VERY_STRICT   2 ///< Strictly conform to an older more strict version of the spec or reference software.\n#define FF_COMPLIANCE_STRICT        1 ///< Strictly conform to all the things in the spec no matter what consequences.\n#define FF_COMPLIANCE_NORMAL        0\n#define FF_COMPLIANCE_UNOFFICIAL   -1 ///< Allow unofficial extensions\n#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things.\n\n    /**\n     * error concealment flags\n     * - encoding: unused\n     * - decoding: Set by user.\n     */\n    int error_concealment;\n#define FF_EC_GUESS_MVS   1\n#define FF_EC_DEBLOCK     2\n#define FF_EC_FAVOR_INTER 256\n\n    /**\n     * debug\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     */\n    int debug;\n#define FF_DEBUG_PICT_INFO   1\n#define FF_DEBUG_RC          2\n#define FF_DEBUG_BITSTREAM   4\n#define FF_DEBUG_MB_TYPE     8\n#define FF_DEBUG_QP          16\n#define FF_DEBUG_DCT_COEFF   0x00000040\n#define FF_DEBUG_SKIP        0x00000080\n#define FF_DEBUG_STARTCODE   0x00000100\n#define FF_DEBUG_ER          0x00000400\n#define FF_DEBUG_MMCO        0x00000800\n#define FF_DEBUG_BUGS        0x00001000\n#define FF_DEBUG_BUFFERS     0x00008000\n#define FF_DEBUG_THREADS     0x00010000\n#define FF_DEBUG_GREEN_MD    0x00800000\n#define FF_DEBUG_NOMC        0x01000000\n\n    /**\n     * Error recognition; may misdetect some more or less valid parts as errors.\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     */\n    int err_recognition;\n\n/**\n * Verify checksums embedded in the bitstream (could be of either encoded or\n * decoded data, depending on the codec) and print an error message on mismatch.\n * If AV_EF_EXPLODE is also set, a mismatching checksum will result in the\n * decoder returning an error.\n */\n#define AV_EF_CRCCHECK  (1<<0)\n#define AV_EF_BITSTREAM (1<<1)          ///< detect bitstream specification deviations\n#define AV_EF_BUFFER    (1<<2)          ///< detect improper bitstream length\n#define AV_EF_EXPLODE   (1<<3)          ///< abort decoding on minor error detection\n\n#define AV_EF_IGNORE_ERR (1<<15)        ///< ignore errors and continue\n#define AV_EF_CAREFUL    (1<<16)        ///< consider things that violate the spec, are fast to calculate and have not been seen in the wild as errors\n#define AV_EF_COMPLIANT  (1<<17)        ///< consider all spec non compliances as errors\n#define AV_EF_AGGRESSIVE (1<<18)        ///< consider things that a sane encoder should not do as an error\n\n\n    /**\n     * opaque 64-bit number (generally a PTS) that will be reordered and\n     * output in AVFrame.reordered_opaque\n     * - encoding: Set by libavcodec to the reordered_opaque of the input\n     *             frame corresponding to the last returned packet. Only\n     *             supported by encoders with the\n     *             AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability.\n     * - decoding: Set by user.\n     */\n    int64_t reordered_opaque;\n\n    /**\n     * Hardware accelerator in use\n     * - encoding: unused.\n     * - decoding: Set by libavcodec\n     */\n    const struct AVHWAccel *hwaccel;\n\n    /**\n     * Hardware accelerator context.\n     * For some hardware accelerators, a global context needs to be\n     * provided by the user. In that case, this holds display-dependent\n     * data FFmpeg cannot instantiate itself. Please refer to the\n     * FFmpeg HW accelerator documentation to know how to fill this.\n     * - encoding: unused\n     * - decoding: Set by user\n     */\n    void *hwaccel_context;\n\n    /**\n     * error\n     * - encoding: Set by libavcodec if flags & AV_CODEC_FLAG_PSNR.\n     * - decoding: unused\n     */\n    uint64_t error[AV_NUM_DATA_POINTERS];\n\n    /**\n     * DCT algorithm, see FF_DCT_* below\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n    int dct_algo;\n#define FF_DCT_AUTO    0\n#define FF_DCT_FASTINT 1\n#define FF_DCT_INT     2\n#define FF_DCT_MMX     3\n#define FF_DCT_ALTIVEC 5\n#define FF_DCT_FAAN    6\n\n    /**\n     * IDCT algorithm, see FF_IDCT_* below.\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     */\n    int idct_algo;\n#define FF_IDCT_AUTO          0\n#define FF_IDCT_INT           1\n#define FF_IDCT_SIMPLE        2\n#define FF_IDCT_SIMPLEMMX     3\n#define FF_IDCT_ARM           7\n#define FF_IDCT_ALTIVEC       8\n#define FF_IDCT_SIMPLEARM     10\n#define FF_IDCT_XVID          14\n#define FF_IDCT_SIMPLEARMV5TE 16\n#define FF_IDCT_SIMPLEARMV6   17\n#define FF_IDCT_FAAN          20\n#define FF_IDCT_SIMPLENEON    22\n#if FF_API_IDCT_NONE\n// formerly used by xvmc\n#define FF_IDCT_NONE          24\n#endif\n#define FF_IDCT_SIMPLEAUTO    128\n\n    /**\n     * bits per sample/pixel from the demuxer (needed for huffyuv).\n     * - encoding: Set by libavcodec.\n     * - decoding: Set by user.\n     */\n     int bits_per_coded_sample;\n\n    /**\n     * Bits per sample/pixel of internal libavcodec pixel/sample format.\n     * - encoding: set by user.\n     * - decoding: set by libavcodec.\n     */\n    int bits_per_raw_sample;\n\n    /**\n     * low resolution decoding, 1-> 1/2 size, 2->1/4 size\n     * - encoding: unused\n     * - decoding: Set by user.\n     */\n     int lowres;\n\n    /**\n     * thread count\n     * is used to decide how many independent tasks should be passed to execute()\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     */\n    int thread_count;\n\n    /**\n     * Which multithreading methods to use.\n     * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread,\n     * so clients which cannot provide future frames should not use it.\n     *\n     * - encoding: Set by user, otherwise the default is used.\n     * - decoding: Set by user, otherwise the default is used.\n     */\n    int thread_type;\n#define FF_THREAD_FRAME   1 ///< Decode more than one frame at once\n#define FF_THREAD_SLICE   2 ///< Decode more than one part of a single frame at once\n\n    /**\n     * Which multithreading methods are in use by the codec.\n     * - encoding: Set by libavcodec.\n     * - decoding: Set by libavcodec.\n     */\n    int active_thread_type;\n\n#if FF_API_THREAD_SAFE_CALLBACKS\n    /**\n     * Set by the client if its custom get_buffer() callback can be called\n     * synchronously from another thread, which allows faster multithreaded decoding.\n     * draw_horiz_band() will be called from other threads regardless of this setting.\n     * Ignored if the default get_buffer() is used.\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     *\n     * @deprecated the custom get_buffer2() callback should always be\n     *   thread-safe. Thread-unsafe get_buffer2() implementations will be\n     *   invalid starting with LIBAVCODEC_VERSION_MAJOR=60; in other words,\n     *   libavcodec will behave as if this field was always set to 1.\n     *   Callers that want to be forward compatible with future libavcodec\n     *   versions should wrap access to this field in\n     *     #if LIBAVCODEC_VERSION_MAJOR < 60\n     */\n    attribute_deprecated\n    int thread_safe_callbacks;\n#endif\n\n    /**\n     * The codec may call this to execute several independent things.\n     * It will return only after finishing all tasks.\n     * The user may replace this with some multithreaded implementation,\n     * the default implementation will execute the parts serially.\n     * @param count the number of things to execute\n     * - encoding: Set by libavcodec, user can override.\n     * - decoding: Set by libavcodec, user can override.\n     */\n    int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size);\n\n    /**\n     * The codec may call this to execute several independent things.\n     * It will return only after finishing all tasks.\n     * The user may replace this with some multithreaded implementation,\n     * the default implementation will execute the parts serially.\n     * @param c context passed also to func\n     * @param count the number of things to execute\n     * @param arg2 argument passed unchanged to func\n     * @param ret return values of executed functions, must have space for \"count\" values. May be NULL.\n     * @param func function that will be called count times, with jobnr from 0 to count-1.\n     *             threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no\n     *             two instances of func executing at the same time will have the same threadnr.\n     * @return always 0 currently, but code should handle a future improvement where when any call to func\n     *         returns < 0 no further calls to func may be done and < 0 is returned.\n     * - encoding: Set by libavcodec, user can override.\n     * - decoding: Set by libavcodec, user can override.\n     */\n    int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count);\n\n    /**\n     * noise vs. sse weight for the nsse comparison function\n     * - encoding: Set by user.\n     * - decoding: unused\n     */\n     int nsse_weight;\n\n    /**\n     * profile\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n     int profile;\n#define FF_PROFILE_UNKNOWN -99\n#define FF_PROFILE_RESERVED -100\n\n#define FF_PROFILE_AAC_MAIN 0\n#define FF_PROFILE_AAC_LOW  1\n#define FF_PROFILE_AAC_SSR  2\n#define FF_PROFILE_AAC_LTP  3\n#define FF_PROFILE_AAC_HE   4\n#define FF_PROFILE_AAC_HE_V2 28\n#define FF_PROFILE_AAC_LD   22\n#define FF_PROFILE_AAC_ELD  38\n#define FF_PROFILE_MPEG2_AAC_LOW 128\n#define FF_PROFILE_MPEG2_AAC_HE  131\n\n#define FF_PROFILE_DNXHD         0\n#define FF_PROFILE_DNXHR_LB      1\n#define FF_PROFILE_DNXHR_SQ      2\n#define FF_PROFILE_DNXHR_HQ      3\n#define FF_PROFILE_DNXHR_HQX     4\n#define FF_PROFILE_DNXHR_444     5\n\n#define FF_PROFILE_DTS         20\n#define FF_PROFILE_DTS_ES      30\n#define FF_PROFILE_DTS_96_24   40\n#define FF_PROFILE_DTS_HD_HRA  50\n#define FF_PROFILE_DTS_HD_MA   60\n#define FF_PROFILE_DTS_EXPRESS 70\n\n#define FF_PROFILE_MPEG2_422    0\n#define FF_PROFILE_MPEG2_HIGH   1\n#define FF_PROFILE_MPEG2_SS     2\n#define FF_PROFILE_MPEG2_SNR_SCALABLE  3\n#define FF_PROFILE_MPEG2_MAIN   4\n#define FF_PROFILE_MPEG2_SIMPLE 5\n\n#define FF_PROFILE_H264_CONSTRAINED  (1<<9)  // 8+1; constraint_set1_flag\n#define FF_PROFILE_H264_INTRA        (1<<11) // 8+3; constraint_set3_flag\n\n#define FF_PROFILE_H264_BASELINE             66\n#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED)\n#define FF_PROFILE_H264_MAIN                 77\n#define FF_PROFILE_H264_EXTENDED             88\n#define FF_PROFILE_H264_HIGH                 100\n#define FF_PROFILE_H264_HIGH_10              110\n#define FF_PROFILE_H264_HIGH_10_INTRA        (110|FF_PROFILE_H264_INTRA)\n#define FF_PROFILE_H264_MULTIVIEW_HIGH       118\n#define FF_PROFILE_H264_HIGH_422             122\n#define FF_PROFILE_H264_HIGH_422_INTRA       (122|FF_PROFILE_H264_INTRA)\n#define FF_PROFILE_H264_STEREO_HIGH          128\n#define FF_PROFILE_H264_HIGH_444             144\n#define FF_PROFILE_H264_HIGH_444_PREDICTIVE  244\n#define FF_PROFILE_H264_HIGH_444_INTRA       (244|FF_PROFILE_H264_INTRA)\n#define FF_PROFILE_H264_CAVLC_444            44\n\n#define FF_PROFILE_VC1_SIMPLE   0\n#define FF_PROFILE_VC1_MAIN     1\n#define FF_PROFILE_VC1_COMPLEX  2\n#define FF_PROFILE_VC1_ADVANCED 3\n\n#define FF_PROFILE_MPEG4_SIMPLE                     0\n#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE            1\n#define FF_PROFILE_MPEG4_CORE                       2\n#define FF_PROFILE_MPEG4_MAIN                       3\n#define FF_PROFILE_MPEG4_N_BIT                      4\n#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE           5\n#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION      6\n#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE     7\n#define FF_PROFILE_MPEG4_HYBRID                     8\n#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME         9\n#define FF_PROFILE_MPEG4_CORE_SCALABLE             10\n#define FF_PROFILE_MPEG4_ADVANCED_CODING           11\n#define FF_PROFILE_MPEG4_ADVANCED_CORE             12\n#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13\n#define FF_PROFILE_MPEG4_SIMPLE_STUDIO             14\n#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE           15\n\n#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0   1\n#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1   2\n#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION  32768\n#define FF_PROFILE_JPEG2000_DCINEMA_2K              3\n#define FF_PROFILE_JPEG2000_DCINEMA_4K              4\n\n#define FF_PROFILE_VP9_0                            0\n#define FF_PROFILE_VP9_1                            1\n#define FF_PROFILE_VP9_2                            2\n#define FF_PROFILE_VP9_3                            3\n\n#define FF_PROFILE_HEVC_MAIN                        1\n#define FF_PROFILE_HEVC_MAIN_10                     2\n#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE          3\n#define FF_PROFILE_HEVC_REXT                        4\n\n#define FF_PROFILE_VVC_MAIN_10                      1\n#define FF_PROFILE_VVC_MAIN_10_444                 33\n\n#define FF_PROFILE_AV1_MAIN                         0\n#define FF_PROFILE_AV1_HIGH                         1\n#define FF_PROFILE_AV1_PROFESSIONAL                 2\n\n#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT            0xc0\n#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1\n#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT         0xc2\n#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS                0xc3\n#define FF_PROFILE_MJPEG_JPEG_LS                         0xf7\n\n#define FF_PROFILE_SBC_MSBC                         1\n\n#define FF_PROFILE_PRORES_PROXY     0\n#define FF_PROFILE_PRORES_LT        1\n#define FF_PROFILE_PRORES_STANDARD  2\n#define FF_PROFILE_PRORES_HQ        3\n#define FF_PROFILE_PRORES_4444      4\n#define FF_PROFILE_PRORES_XQ        5\n\n#define FF_PROFILE_ARIB_PROFILE_A 0\n#define FF_PROFILE_ARIB_PROFILE_C 1\n\n#define FF_PROFILE_KLVA_SYNC 0\n#define FF_PROFILE_KLVA_ASYNC 1\n\n    /**\n     * level\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n     int level;\n#define FF_LEVEL_UNKNOWN -99\n\n    /**\n     * Skip loop filtering for selected frames.\n     * - encoding: unused\n     * - decoding: Set by user.\n     */\n    enum AVDiscard skip_loop_filter;\n\n    /**\n     * Skip IDCT/dequantization for selected frames.\n     * - encoding: unused\n     * - decoding: Set by user.\n     */\n    enum AVDiscard skip_idct;\n\n    /**\n     * Skip decoding for selected frames.\n     * - encoding: unused\n     * - decoding: Set by user.\n     */\n    enum AVDiscard skip_frame;\n\n    /**\n     * Header containing style information for text subtitles.\n     * For SUBTITLE_ASS subtitle type, it should contain the whole ASS\n     * [Script Info] and [V4+ Styles] section, plus the [Events] line and\n     * the Format line following. It shouldn't include any Dialogue line.\n     * - encoding: Set/allocated/freed by user (before avcodec_open2())\n     * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2())\n     */\n    uint8_t *subtitle_header;\n    int subtitle_header_size;\n\n    /**\n     * Audio only. The number of \"priming\" samples (padding) inserted by the\n     * encoder at the beginning of the audio. I.e. this number of leading\n     * decoded samples must be discarded by the caller to get the original audio\n     * without leading padding.\n     *\n     * - decoding: unused\n     * - encoding: Set by libavcodec. The timestamps on the output packets are\n     *             adjusted by the encoder so that they always refer to the\n     *             first sample of the data actually contained in the packet,\n     *             including any added padding.  E.g. if the timebase is\n     *             1/samplerate and the timestamp of the first input sample is\n     *             0, the timestamp of the first output packet will be\n     *             -initial_padding.\n     */\n    int initial_padding;\n\n    /**\n     * - decoding: For codecs that store a framerate value in the compressed\n     *             bitstream, the decoder may export it here. { 0, 1} when\n     *             unknown.\n     * - encoding: May be used to signal the framerate of CFR content to an\n     *             encoder.\n     */\n    AVRational framerate;\n\n    /**\n     * Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.\n     * - encoding: unused.\n     * - decoding: Set by libavcodec before calling get_format()\n     */\n    enum AVPixelFormat sw_pix_fmt;\n\n    /**\n     * Timebase in which pkt_dts/pts and AVPacket.dts/pts are.\n     * - encoding unused.\n     * - decoding set by user.\n     */\n    AVRational pkt_timebase;\n\n    /**\n     * AVCodecDescriptor\n     * - encoding: unused.\n     * - decoding: set by libavcodec.\n     */\n    const AVCodecDescriptor *codec_descriptor;\n\n    /**\n     * Current statistics for PTS correction.\n     * - decoding: maintained and used by libavcodec, not intended to be used by user apps\n     * - encoding: unused\n     */\n    int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far\n    int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far\n    int64_t pts_correction_last_pts;       /// PTS of the last frame\n    int64_t pts_correction_last_dts;       /// DTS of the last frame\n\n    /**\n     * Character encoding of the input subtitles file.\n     * - decoding: set by user\n     * - encoding: unused\n     */\n    char *sub_charenc;\n\n    /**\n     * Subtitles character encoding mode. Formats or codecs might be adjusting\n     * this setting (if they are doing the conversion themselves for instance).\n     * - decoding: set by libavcodec\n     * - encoding: unused\n     */\n    int sub_charenc_mode;\n#define FF_SUB_CHARENC_MODE_DO_NOTHING  -1  ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance)\n#define FF_SUB_CHARENC_MODE_AUTOMATIC    0  ///< libavcodec will select the mode itself\n#define FF_SUB_CHARENC_MODE_PRE_DECODER  1  ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv\n#define FF_SUB_CHARENC_MODE_IGNORE       2  ///< neither convert the subtitles, nor check them for valid UTF-8\n\n    /**\n     * Skip processing alpha if supported by codec.\n     * Note that if the format uses pre-multiplied alpha (common with VP6,\n     * and recommended due to better video quality/compression)\n     * the image will look as if alpha-blended onto a black background.\n     * However for formats that do not use pre-multiplied alpha\n     * there might be serious artefacts (though e.g. libswscale currently\n     * assumes pre-multiplied alpha anyway).\n     *\n     * - decoding: set by user\n     * - encoding: unused\n     */\n    int skip_alpha;\n\n    /**\n     * Number of samples to skip after a discontinuity\n     * - decoding: unused\n     * - encoding: set by libavcodec\n     */\n    int seek_preroll;\n\n#if FF_API_DEBUG_MV\n    /**\n     * @deprecated unused\n     */\n    attribute_deprecated\n    int debug_mv;\n#define FF_DEBUG_VIS_MV_P_FOR  0x00000001 //visualize forward predicted MVs of P frames\n#define FF_DEBUG_VIS_MV_B_FOR  0x00000002 //visualize forward predicted MVs of B frames\n#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames\n#endif\n\n    /**\n     * custom intra quantization matrix\n     * - encoding: Set by user, can be NULL.\n     * - decoding: unused.\n     */\n    uint16_t *chroma_intra_matrix;\n\n    /**\n     * dump format separator.\n     * can be \", \" or \"\\n      \" or anything else\n     * - encoding: Set by user.\n     * - decoding: Set by user.\n     */\n    uint8_t *dump_separator;\n\n    /**\n     * ',' separated list of allowed decoders.\n     * If NULL then all are allowed\n     * - encoding: unused\n     * - decoding: set by user\n     */\n    char *codec_whitelist;\n\n    /**\n     * Properties of the stream that gets decoded\n     * - encoding: unused\n     * - decoding: set by libavcodec\n     */\n    unsigned properties;\n#define FF_CODEC_PROPERTY_LOSSLESS        0x00000001\n#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002\n#define FF_CODEC_PROPERTY_FILM_GRAIN      0x00000004\n\n    /**\n     * Additional data associated with the entire coded stream.\n     *\n     * - decoding: unused\n     * - encoding: may be set by libavcodec after avcodec_open2().\n     */\n    AVPacketSideData *coded_side_data;\n    int            nb_coded_side_data;\n\n    /**\n     * A reference to the AVHWFramesContext describing the input (for encoding)\n     * or output (decoding) frames. The reference is set by the caller and\n     * afterwards owned (and freed) by libavcodec - it should never be read by\n     * the caller after being set.\n     *\n     * - decoding: This field should be set by the caller from the get_format()\n     *             callback. The previous reference (if any) will always be\n     *             unreffed by libavcodec before the get_format() call.\n     *\n     *             If the default get_buffer2() is used with a hwaccel pixel\n     *             format, then this AVHWFramesContext will be used for\n     *             allocating the frame buffers.\n     *\n     * - encoding: For hardware encoders configured to use a hwaccel pixel\n     *             format, this field should be set by the caller to a reference\n     *             to the AVHWFramesContext describing input frames.\n     *             AVHWFramesContext.format must be equal to\n     *             AVCodecContext.pix_fmt.\n     *\n     *             This field should be set before avcodec_open2() is called.\n     */\n    AVBufferRef *hw_frames_ctx;\n\n#if FF_API_SUB_TEXT_FORMAT\n    /**\n     * @deprecated unused\n     */\n    attribute_deprecated\n    int sub_text_format;\n#define FF_SUB_TEXT_FMT_ASS              0\n#endif\n\n    /**\n     * Audio only. The amount of padding (in samples) appended by the encoder to\n     * the end of the audio. I.e. this number of decoded samples must be\n     * discarded by the caller from the end of the stream to get the original\n     * audio without any trailing padding.\n     *\n     * - decoding: unused\n     * - encoding: unused\n     */\n    int trailing_padding;\n\n    /**\n     * The number of pixels per image to maximally accept.\n     *\n     * - decoding: set by user\n     * - encoding: set by user\n     */\n    int64_t max_pixels;\n\n    /**\n     * A reference to the AVHWDeviceContext describing the device which will\n     * be used by a hardware encoder/decoder.  The reference is set by the\n     * caller and afterwards owned (and freed) by libavcodec.\n     *\n     * This should be used if either the codec device does not require\n     * hardware frames or any that are used are to be allocated internally by\n     * libavcodec.  If the user wishes to supply any of the frames used as\n     * encoder input or decoder output then hw_frames_ctx should be used\n     * instead.  When hw_frames_ctx is set in get_format() for a decoder, this\n     * field will be ignored while decoding the associated stream segment, but\n     * may again be used on a following one after another get_format() call.\n     *\n     * For both encoders and decoders this field should be set before\n     * avcodec_open2() is called and must not be written to thereafter.\n     *\n     * Note that some decoders may require this field to be set initially in\n     * order to support hw_frames_ctx at all - in that case, all frames\n     * contexts used must be created on the same device.\n     */\n    AVBufferRef *hw_device_ctx;\n\n    /**\n     * Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated\n     * decoding (if active).\n     * - encoding: unused\n     * - decoding: Set by user (either before avcodec_open2(), or in the\n     *             AVCodecContext.get_format callback)\n     */\n    int hwaccel_flags;\n\n    /**\n     * Video decoding only. Certain video codecs support cropping, meaning that\n     * only a sub-rectangle of the decoded frame is intended for display.  This\n     * option controls how cropping is handled by libavcodec.\n     *\n     * When set to 1 (the default), libavcodec will apply cropping internally.\n     * I.e. it will modify the output frame width/height fields and offset the\n     * data pointers (only by as much as possible while preserving alignment, or\n     * by the full amount if the AV_CODEC_FLAG_UNALIGNED flag is set) so that\n     * the frames output by the decoder refer only to the cropped area. The\n     * crop_* fields of the output frames will be zero.\n     *\n     * When set to 0, the width/height fields of the output frames will be set\n     * to the coded dimensions and the crop_* fields will describe the cropping\n     * rectangle. Applying the cropping is left to the caller.\n     *\n     * @warning When hardware acceleration with opaque output frames is used,\n     * libavcodec is unable to apply cropping from the top/left border.\n     *\n     * @note when this option is set to zero, the width/height fields of the\n     * AVCodecContext and output AVFrames have different meanings. The codec\n     * context fields store display dimensions (with the coded dimensions in\n     * coded_width/height), while the frame fields store the coded dimensions\n     * (with the display dimensions being determined by the crop_* fields).\n     */\n    int apply_cropping;\n\n    /*\n     * Video decoding only.  Sets the number of extra hardware frames which\n     * the decoder will allocate for use by the caller.  This must be set\n     * before avcodec_open2() is called.\n     *\n     * Some hardware decoders require all frames that they will use for\n     * output to be defined in advance before decoding starts.  For such\n     * decoders, the hardware frame pool must therefore be of a fixed size.\n     * The extra frames set here are on top of any number that the decoder\n     * needs internally in order to operate normally (for example, frames\n     * used as reference pictures).\n     */\n    int extra_hw_frames;\n\n    /**\n     * The percentage of damaged samples to discard a frame.\n     *\n     * - decoding: set by user\n     * - encoding: unused\n     */\n    int discard_damaged_percentage;\n\n    /**\n     * The number of samples per frame to maximally accept.\n     *\n     * - decoding: set by user\n     * - encoding: set by user\n     */\n    int64_t max_samples;\n\n    /**\n     * Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of\n     * metadata exported in frame, packet, or coded stream side data by\n     * decoders and encoders.\n     *\n     * - decoding: set by user\n     * - encoding: set by user\n     */\n    int export_side_data;\n\n    /**\n     * This callback is called at the beginning of each packet to get a data\n     * buffer for it.\n     *\n     * The following field will be set in the packet before this callback is\n     * called:\n     * - size\n     * This callback must use the above value to calculate the required buffer size,\n     * which must padded by at least AV_INPUT_BUFFER_PADDING_SIZE bytes.\n     *\n     * In some specific cases, the encoder may not use the entire buffer allocated by this\n     * callback. This will be reflected in the size value in the packet once returned by\n     * avcodec_receive_packet().\n     *\n     * This callback must fill the following fields in the packet:\n     * - data: alignment requirements for AVPacket apply, if any. Some architectures and\n     *   encoders may benefit from having aligned data.\n     * - buf: must contain a pointer to an AVBufferRef structure. The packet's\n     *   data pointer must be contained in it. See: av_buffer_create(), av_buffer_alloc(),\n     *   and av_buffer_ref().\n     *\n     * If AV_CODEC_CAP_DR1 is not set then get_encode_buffer() must call\n     * avcodec_default_get_encode_buffer() instead of providing a buffer allocated by\n     * some other means.\n     *\n     * The flags field may contain a combination of AV_GET_ENCODE_BUFFER_FLAG_ flags.\n     * They may be used for example to hint what use the buffer may get after being\n     * created.\n     * Implementations of this callback may ignore flags they don't understand.\n     * If AV_GET_ENCODE_BUFFER_FLAG_REF is set in flags then the packet may be reused\n     * (read and/or written to if it is writable) later by libavcodec.\n     *\n     * This callback must be thread-safe, as when frame threading is used, it may\n     * be called from multiple threads simultaneously.\n     *\n     * @see avcodec_default_get_encode_buffer()\n     *\n     * - encoding: Set by libavcodec, user can override.\n     * - decoding: unused\n     */\n    int (*get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags);\n\n    /**\n     * Audio channel layout.\n     * - encoding: must be set by the caller, to one of AVCodec.ch_layouts.\n     * - decoding: may be set by the caller if known e.g. from the container.\n     *             The decoder can then override during decoding as needed.\n     */\n    AVChannelLayout ch_layout;\n} AVCodecContext;\n\n/**\n * @defgroup lavc_hwaccel AVHWAccel\n *\n * @note  Nothing in this structure should be accessed by the user.  At some\n *        point in future it will not be externally visible at all.\n *\n * @{\n */\ntypedef struct AVHWAccel {\n    /**\n     * Name of the hardware accelerated codec.\n     * The name is globally unique among encoders and among decoders (but an\n     * encoder and a decoder can share the same name).\n     */\n    const char *name;\n\n    /**\n     * Type of codec implemented by the hardware accelerator.\n     *\n     * See AVMEDIA_TYPE_xxx\n     */\n    enum AVMediaType type;\n\n    /**\n     * Codec implemented by the hardware accelerator.\n     *\n     * See AV_CODEC_ID_xxx\n     */\n    enum AVCodecID id;\n\n    /**\n     * Supported pixel format.\n     *\n     * Only hardware accelerated formats are supported here.\n     */\n    enum AVPixelFormat pix_fmt;\n\n    /**\n     * Hardware accelerated codec capabilities.\n     * see AV_HWACCEL_CODEC_CAP_*\n     */\n    int capabilities;\n\n    /*****************************************************************\n     * No fields below this line are part of the public API. They\n     * may not be used outside of libavcodec and can be changed and\n     * removed at will.\n     * New public fields should be added right above.\n     *****************************************************************\n     */\n\n    /**\n     * Allocate a custom buffer\n     */\n    int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame);\n\n    /**\n     * Called at the beginning of each frame or field picture.\n     *\n     * Meaningful frame information (codec specific) is guaranteed to\n     * be parsed at this point. This function is mandatory.\n     *\n     * Note that buf can be NULL along with buf_size set to 0.\n     * Otherwise, this means the whole frame is available at this point.\n     *\n     * @param avctx the codec context\n     * @param buf the frame data buffer base\n     * @param buf_size the size of the frame in bytes\n     * @return zero if successful, a negative value otherwise\n     */\n    int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size);\n\n    /**\n     * Callback for parameter data (SPS/PPS/VPS etc).\n     *\n     * Useful for hardware decoders which keep persistent state about the\n     * video parameters, and need to receive any changes to update that state.\n     *\n     * @param avctx the codec context\n     * @param type the nal unit type\n     * @param buf the nal unit data buffer\n     * @param buf_size the size of the nal unit in bytes\n     * @return zero if successful, a negative value otherwise\n     */\n    int (*decode_params)(AVCodecContext *avctx, int type, const uint8_t *buf, uint32_t buf_size);\n\n    /**\n     * Callback for each slice.\n     *\n     * Meaningful slice information (codec specific) is guaranteed to\n     * be parsed at this point. This function is mandatory.\n     *\n     * @param avctx the codec context\n     * @param buf the slice data buffer base\n     * @param buf_size the size of the slice in bytes\n     * @return zero if successful, a negative value otherwise\n     */\n    int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size);\n\n    /**\n     * Called at the end of each frame or field picture.\n     *\n     * The whole picture is parsed at this point and can now be sent\n     * to the hardware accelerator. This function is mandatory.\n     *\n     * @param avctx the codec context\n     * @return zero if successful, a negative value otherwise\n     */\n    int (*end_frame)(AVCodecContext *avctx);\n\n    /**\n     * Size of per-frame hardware accelerator private data.\n     *\n     * Private data is allocated with av_mallocz() before\n     * AVCodecContext.get_buffer() and deallocated after\n     * AVCodecContext.release_buffer().\n     */\n    int frame_priv_data_size;\n\n    /**\n     * Initialize the hwaccel private data.\n     *\n     * This will be called from ff_get_format(), after hwaccel and\n     * hwaccel_context are set and the hwaccel private data in AVCodecInternal\n     * is allocated.\n     */\n    int (*init)(AVCodecContext *avctx);\n\n    /**\n     * Uninitialize the hwaccel private data.\n     *\n     * This will be called from get_format() or avcodec_close(), after hwaccel\n     * and hwaccel_context are already uninitialized.\n     */\n    int (*uninit)(AVCodecContext *avctx);\n\n    /**\n     * Size of the private data to allocate in\n     * AVCodecInternal.hwaccel_priv_data.\n     */\n    int priv_data_size;\n\n    /**\n     * Internal hwaccel capabilities.\n     */\n    int caps_internal;\n\n    /**\n     * Fill the given hw_frames context with current codec parameters. Called\n     * from get_format. Refer to avcodec_get_hw_frames_parameters() for\n     * details.\n     *\n     * This CAN be called before AVHWAccel.init is called, and you must assume\n     * that avctx->hwaccel_priv_data is invalid.\n     */\n    int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);\n} AVHWAccel;\n\n/**\n * HWAccel is experimental and is thus avoided in favor of non experimental\n * codecs\n */\n#define AV_HWACCEL_CODEC_CAP_EXPERIMENTAL 0x0200\n\n/**\n * Hardware acceleration should be used for decoding even if the codec level\n * used is unknown or higher than the maximum supported level reported by the\n * hardware driver.\n *\n * It's generally a good idea to pass this flag unless you have a specific\n * reason not to, as hardware tends to under-report supported levels.\n */\n#define AV_HWACCEL_FLAG_IGNORE_LEVEL (1 << 0)\n\n/**\n * Hardware acceleration can output YUV pixel formats with a different chroma\n * sampling than 4:2:0 and/or other than 8 bits per component.\n */\n#define AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH (1 << 1)\n\n/**\n * Hardware acceleration should still be attempted for decoding when the\n * codec profile does not match the reported capabilities of the hardware.\n *\n * For example, this can be used to try to decode baseline profile H.264\n * streams in hardware - it will often succeed, because many streams marked\n * as baseline profile actually conform to constrained baseline profile.\n *\n * @warning If the stream is actually not supported then the behaviour is\n *          undefined, and may include returning entirely incorrect output\n *          while indicating success.\n */\n#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH (1 << 2)\n\n/**\n * @}\n */\n\nenum AVSubtitleType {\n    SUBTITLE_NONE,\n\n    SUBTITLE_BITMAP,                ///< A bitmap, pict will be set\n\n    /**\n     * Plain text, the text field must be set by the decoder and is\n     * authoritative. ass and pict fields may contain approximations.\n     */\n    SUBTITLE_TEXT,\n\n    /**\n     * Formatted text, the ass field must be set by the decoder and is\n     * authoritative. pict and text fields may contain approximations.\n     */\n    SUBTITLE_ASS,\n};\n\n#define AV_SUBTITLE_FLAG_FORCED 0x00000001\n\ntypedef struct AVSubtitleRect {\n    int x;         ///< top left corner  of pict, undefined when pict is not set\n    int y;         ///< top left corner  of pict, undefined when pict is not set\n    int w;         ///< width            of pict, undefined when pict is not set\n    int h;         ///< height           of pict, undefined when pict is not set\n    int nb_colors; ///< number of colors in pict, undefined when pict is not set\n\n    /**\n     * data+linesize for the bitmap of this subtitle.\n     * Can be set for text/ass as well once they are rendered.\n     */\n    uint8_t *data[4];\n    int linesize[4];\n\n    enum AVSubtitleType type;\n\n    char *text;                     ///< 0 terminated plain UTF-8 text\n\n    /**\n     * 0 terminated ASS/SSA compatible event line.\n     * The presentation of this is unaffected by the other values in this\n     * struct.\n     */\n    char *ass;\n\n    int flags;\n} AVSubtitleRect;\n\ntypedef struct AVSubtitle {\n    uint16_t format; /* 0 = graphics */\n    uint32_t start_display_time; /* relative to packet pts, in ms */\n    uint32_t end_display_time; /* relative to packet pts, in ms */\n    unsigned num_rects;\n    AVSubtitleRect **rects;\n    int64_t pts;    ///< Same as packet pts, in AV_TIME_BASE\n} AVSubtitle;\n\n/**\n * Return the LIBAVCODEC_VERSION_INT constant.\n */\nunsigned avcodec_version(void);\n\n/**\n * Return the libavcodec build-time configuration.\n */\nconst char *avcodec_configuration(void);\n\n/**\n * Return the libavcodec license.\n */\nconst char *avcodec_license(void);\n\n/**\n * Allocate an AVCodecContext and set its fields to default values. The\n * resulting struct should be freed with avcodec_free_context().\n *\n * @param codec if non-NULL, allocate private data and initialize defaults\n *              for the given codec. It is illegal to then call avcodec_open2()\n *              with a different codec.\n *              If NULL, then the codec-specific defaults won't be initialized,\n *              which may result in suboptimal default settings (this is\n *              important mainly for encoders, e.g. libx264).\n *\n * @return An AVCodecContext filled with default values or NULL on failure.\n */\nAVCodecContext *avcodec_alloc_context3(const AVCodec *codec);\n\n/**\n * Free the codec context and everything associated with it and write NULL to\n * the provided pointer.\n */\nvoid avcodec_free_context(AVCodecContext **avctx);\n\n/**\n * Get the AVClass for AVCodecContext. It can be used in combination with\n * AV_OPT_SEARCH_FAKE_OBJ for examining options.\n *\n * @see av_opt_find().\n */\nconst AVClass *avcodec_get_class(void);\n\n#if FF_API_GET_FRAME_CLASS\n/**\n * @deprecated This function should not be used.\n */\nattribute_deprecated\nconst AVClass *avcodec_get_frame_class(void);\n#endif\n\n/**\n * Get the AVClass for AVSubtitleRect. It can be used in combination with\n * AV_OPT_SEARCH_FAKE_OBJ for examining options.\n *\n * @see av_opt_find().\n */\nconst AVClass *avcodec_get_subtitle_rect_class(void);\n\n/**\n * Fill the parameters struct based on the values from the supplied codec\n * context. Any allocated fields in par are freed and replaced with duplicates\n * of the corresponding fields in codec.\n *\n * @return >= 0 on success, a negative AVERROR code on failure\n */\nint avcodec_parameters_from_context(AVCodecParameters *par,\n                                    const AVCodecContext *codec);\n\n/**\n * Fill the codec context based on the values from the supplied codec\n * parameters. Any allocated fields in codec that have a corresponding field in\n * par are freed and replaced with duplicates of the corresponding field in par.\n * Fields in codec that do not have a counterpart in par are not touched.\n *\n * @return >= 0 on success, a negative AVERROR code on failure.\n */\nint avcodec_parameters_to_context(AVCodecContext *codec,\n                                  const AVCodecParameters *par);\n\n/**\n * Initialize the AVCodecContext to use the given AVCodec. Prior to using this\n * function the context has to be allocated with avcodec_alloc_context3().\n *\n * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),\n * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for\n * retrieving a codec.\n *\n * @note Always call this function before using decoding routines (such as\n * @ref avcodec_receive_frame()).\n *\n * @code\n * av_dict_set(&opts, \"b\", \"2.5M\", 0);\n * codec = avcodec_find_decoder(AV_CODEC_ID_H264);\n * if (!codec)\n *     exit(1);\n *\n * context = avcodec_alloc_context3(codec);\n *\n * if (avcodec_open2(context, codec, opts) < 0)\n *     exit(1);\n * @endcode\n *\n * @param avctx The context to initialize.\n * @param codec The codec to open this context for. If a non-NULL codec has been\n *              previously passed to avcodec_alloc_context3() or\n *              for this context, then this parameter MUST be either NULL or\n *              equal to the previously passed codec.\n * @param options A dictionary filled with AVCodecContext and codec-private options.\n *                On return this object will be filled with options that were not found.\n *\n * @return zero on success, a negative value on error\n * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),\n *      av_dict_set(), av_opt_find().\n */\nint avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);\n\n/**\n * Close a given AVCodecContext and free all the data associated with it\n * (but not the AVCodecContext itself).\n *\n * Calling this function on an AVCodecContext that hasn't been opened will free\n * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL\n * codec. Subsequent calls will do nothing.\n *\n * @note Do not use this function. Use avcodec_free_context() to destroy a\n * codec context (either open or closed). Opening and closing a codec context\n * multiple times is not supported anymore -- use multiple codec contexts\n * instead.\n */\nint avcodec_close(AVCodecContext *avctx);\n\n/**\n * Free all allocated data in the given subtitle struct.\n *\n * @param sub AVSubtitle to free.\n */\nvoid avsubtitle_free(AVSubtitle *sub);\n\n/**\n * @}\n */\n\n/**\n * @addtogroup lavc_decoding\n * @{\n */\n\n/**\n * The default callback for AVCodecContext.get_buffer2(). It is made public so\n * it can be called by custom get_buffer2() implementations for decoders without\n * AV_CODEC_CAP_DR1 set.\n */\nint avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags);\n\n/**\n * The default callback for AVCodecContext.get_encode_buffer(). It is made public so\n * it can be called by custom get_encode_buffer() implementations for encoders without\n * AV_CODEC_CAP_DR1 set.\n */\nint avcodec_default_get_encode_buffer(AVCodecContext *s, AVPacket *pkt, int flags);\n\n/**\n * Modify width and height values so that they will result in a memory\n * buffer that is acceptable for the codec if you do not use any horizontal\n * padding.\n *\n * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened.\n */\nvoid avcodec_align_dimensions(AVCodecContext *s, int *width, int *height);\n\n/**\n * Modify width and height values so that they will result in a memory\n * buffer that is acceptable for the codec if you also ensure that all\n * line sizes are a multiple of the respective linesize_align[i].\n *\n * May only be used if a codec with AV_CODEC_CAP_DR1 has been opened.\n */\nvoid avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,\n                               int linesize_align[AV_NUM_DATA_POINTERS]);\n\n/**\n * Converts AVChromaLocation to swscale x/y chroma position.\n *\n * The positions represent the chroma (0,0) position in a coordinates system\n * with luma (0,0) representing the origin and luma(1,1) representing 256,256\n *\n * @param xpos  horizontal chroma sample position\n * @param ypos  vertical   chroma sample position\n */\nint avcodec_enum_to_chroma_pos(int *xpos, int *ypos, enum AVChromaLocation pos);\n\n/**\n * Converts swscale x/y chroma position to AVChromaLocation.\n *\n * The positions represent the chroma (0,0) position in a coordinates system\n * with luma (0,0) representing the origin and luma(1,1) representing 256,256\n *\n * @param xpos  horizontal chroma sample position\n * @param ypos  vertical   chroma sample position\n */\nenum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos);\n\n/**\n * Decode a subtitle message.\n * Return a negative value on error, otherwise return the number of bytes used.\n * If no subtitle could be decompressed, got_sub_ptr is zero.\n * Otherwise, the subtitle is stored in *sub.\n * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for\n * simplicity, because the performance difference is expected to be negligible\n * and reusing a get_buffer written for video codecs would probably perform badly\n * due to a potentially very different allocation pattern.\n *\n * Some decoders (those marked with AV_CODEC_CAP_DELAY) have a delay between input\n * and output. This means that for some packets they will not immediately\n * produce decoded output and need to be flushed at the end of decoding to get\n * all the decoded data. Flushing is done by calling this function with packets\n * with avpkt->data set to NULL and avpkt->size set to 0 until it stops\n * returning subtitles. It is safe to flush even those decoders that are not\n * marked with AV_CODEC_CAP_DELAY, then no subtitles will be returned.\n *\n * @note The AVCodecContext MUST have been opened with @ref avcodec_open2()\n * before packets may be fed to the decoder.\n *\n * @param avctx the codec context\n * @param[out] sub The preallocated AVSubtitle in which the decoded subtitle will be stored,\n *                 must be freed with avsubtitle_free if *got_sub_ptr is set.\n * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero.\n * @param[in] avpkt The input AVPacket containing the input buffer.\n */\nint avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,\n                            int *got_sub_ptr,\n                            AVPacket *avpkt);\n\n/**\n * Supply raw packet data as input to a decoder.\n *\n * Internally, this call will copy relevant AVCodecContext fields, which can\n * influence decoding per-packet, and apply them when the packet is actually\n * decoded. (For example AVCodecContext.skip_frame, which might direct the\n * decoder to drop the frame contained by the packet sent with this function.)\n *\n * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE\n *          larger than the actual read bytes because some optimized bitstream\n *          readers read 32 or 64 bits at once and could read over the end.\n *\n * @note The AVCodecContext MUST have been opened with @ref avcodec_open2()\n *       before packets may be fed to the decoder.\n *\n * @param avctx codec context\n * @param[in] avpkt The input AVPacket. Usually, this will be a single video\n *                  frame, or several complete audio frames.\n *                  Ownership of the packet remains with the caller, and the\n *                  decoder will not write to the packet. The decoder may create\n *                  a reference to the packet data (or copy it if the packet is\n *                  not reference-counted).\n *                  Unlike with older APIs, the packet is always fully consumed,\n *                  and if it contains multiple frames (e.g. some audio codecs),\n *                  will require you to call avcodec_receive_frame() multiple\n *                  times afterwards before you can send a new packet.\n *                  It can be NULL (or an AVPacket with data set to NULL and\n *                  size set to 0); in this case, it is considered a flush\n *                  packet, which signals the end of the stream. Sending the\n *                  first flush packet will return success. Subsequent ones are\n *                  unnecessary and will return AVERROR_EOF. If the decoder\n *                  still has frames buffered, it will return them after sending\n *                  a flush packet.\n *\n * @return 0 on success, otherwise negative error code:\n *      AVERROR(EAGAIN):   input is not accepted in the current state - user\n *                         must read output with avcodec_receive_frame() (once\n *                         all output is read, the packet should be resent, and\n *                         the call will not fail with EAGAIN).\n *      AVERROR_EOF:       the decoder has been flushed, and no new packets can\n *                         be sent to it (also returned if more than 1 flush\n *                         packet is sent)\n *      AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush\n *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar\n *      other errors: legitimate decoding errors\n */\nint avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);\n\n/**\n * Return decoded output data from a decoder.\n *\n * @param avctx codec context\n * @param frame This will be set to a reference-counted video or audio\n *              frame (depending on the decoder type) allocated by the\n *              decoder. Note that the function will always call\n *              av_frame_unref(frame) before doing anything else.\n *\n * @return\n *      0:                 success, a frame was returned\n *      AVERROR(EAGAIN):   output is not available in this state - user must try\n *                         to send new input\n *      AVERROR_EOF:       the decoder has been fully flushed, and there will be\n *                         no more output frames\n *      AVERROR(EINVAL):   codec not opened, or it is an encoder\n *      AVERROR_INPUT_CHANGED:   current decoded frame has changed parameters\n *                               with respect to first decoded frame. Applicable\n *                               when flag AV_CODEC_FLAG_DROPCHANGED is set.\n *      other negative values: legitimate decoding errors\n */\nint avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);\n\n/**\n * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet()\n * to retrieve buffered output packets.\n *\n * @param avctx     codec context\n * @param[in] frame AVFrame containing the raw audio or video frame to be encoded.\n *                  Ownership of the frame remains with the caller, and the\n *                  encoder will not write to the frame. The encoder may create\n *                  a reference to the frame data (or copy it if the frame is\n *                  not reference-counted).\n *                  It can be NULL, in which case it is considered a flush\n *                  packet.  This signals the end of the stream. If the encoder\n *                  still has packets buffered, it will return them after this\n *                  call. Once flushing mode has been entered, additional flush\n *                  packets are ignored, and sending frames will return\n *                  AVERROR_EOF.\n *\n *                  For audio:\n *                  If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame\n *                  can have any number of samples.\n *                  If it is not set, frame->nb_samples must be equal to\n *                  avctx->frame_size for all frames except the last.\n *                  The final frame may be smaller than avctx->frame_size.\n * @return 0 on success, otherwise negative error code:\n *      AVERROR(EAGAIN):   input is not accepted in the current state - user\n *                         must read output with avcodec_receive_packet() (once\n *                         all output is read, the packet should be resent, and\n *                         the call will not fail with EAGAIN).\n *      AVERROR_EOF:       the encoder has been flushed, and no new frames can\n *                         be sent to it\n *      AVERROR(EINVAL):   codec not opened, it is a decoder, or requires flush\n *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar\n *      other errors: legitimate encoding errors\n */\nint avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);\n\n/**\n * Read encoded data from the encoder.\n *\n * @param avctx codec context\n * @param avpkt This will be set to a reference-counted packet allocated by the\n *              encoder. Note that the function will always call\n *              av_packet_unref(avpkt) before doing anything else.\n * @return 0 on success, otherwise negative error code:\n *      AVERROR(EAGAIN):   output is not available in the current state - user\n *                         must try to send input\n *      AVERROR_EOF:       the encoder has been fully flushed, and there will be\n *                         no more output packets\n *      AVERROR(EINVAL):   codec not opened, or it is a decoder\n *      other errors: legitimate encoding errors\n */\nint avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);\n\n/**\n * Create and return a AVHWFramesContext with values adequate for hardware\n * decoding. This is meant to get called from the get_format callback, and is\n * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx.\n * This API is for decoding with certain hardware acceleration modes/APIs only.\n *\n * The returned AVHWFramesContext is not initialized. The caller must do this\n * with av_hwframe_ctx_init().\n *\n * Calling this function is not a requirement, but makes it simpler to avoid\n * codec or hardware API specific details when manually allocating frames.\n *\n * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx,\n * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes\n * it unnecessary to call this function or having to care about\n * AVHWFramesContext initialization at all.\n *\n * There are a number of requirements for calling this function:\n *\n * - It must be called from get_format with the same avctx parameter that was\n *   passed to get_format. Calling it outside of get_format is not allowed, and\n *   can trigger undefined behavior.\n * - The function is not always supported (see description of return values).\n *   Even if this function returns successfully, hwaccel initialization could\n *   fail later. (The degree to which implementations check whether the stream\n *   is actually supported varies. Some do this check only after the user's\n *   get_format callback returns.)\n * - The hw_pix_fmt must be one of the choices suggested by get_format. If the\n *   user decides to use a AVHWFramesContext prepared with this API function,\n *   the user must return the same hw_pix_fmt from get_format.\n * - The device_ref passed to this function must support the given hw_pix_fmt.\n * - After calling this API function, it is the user's responsibility to\n *   initialize the AVHWFramesContext (returned by the out_frames_ref parameter),\n *   and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done\n *   before returning from get_format (this is implied by the normal\n *   AVCodecContext.hw_frames_ctx API rules).\n * - The AVHWFramesContext parameters may change every time time get_format is\n *   called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So\n *   you are inherently required to go through this process again on every\n *   get_format call.\n * - It is perfectly possible to call this function without actually using\n *   the resulting AVHWFramesContext. One use-case might be trying to reuse a\n *   previously initialized AVHWFramesContext, and calling this API function\n *   only to test whether the required frame parameters have changed.\n * - Fields that use dynamically allocated values of any kind must not be set\n *   by the user unless setting them is explicitly allowed by the documentation.\n *   If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque,\n *   the new free callback must call the potentially set previous free callback.\n *   This API call may set any dynamically allocated fields, including the free\n *   callback.\n *\n * The function will set at least the following fields on AVHWFramesContext\n * (potentially more, depending on hwaccel API):\n *\n * - All fields set by av_hwframe_ctx_alloc().\n * - Set the format field to hw_pix_fmt.\n * - Set the sw_format field to the most suited and most versatile format. (An\n *   implication is that this will prefer generic formats over opaque formats\n *   with arbitrary restrictions, if possible.)\n * - Set the width/height fields to the coded frame size, rounded up to the\n *   API-specific minimum alignment.\n * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size\n *   field to the number of maximum reference surfaces possible with the codec,\n *   plus 1 surface for the user to work (meaning the user can safely reference\n *   at most 1 decoded surface at a time), plus additional buffering introduced\n *   by frame threading. If the hwaccel does not require pre-allocation, the\n *   field is left to 0, and the decoder will allocate new surfaces on demand\n *   during decoding.\n * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying\n *   hardware API.\n *\n * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but\n * with basic frame parameters set.\n *\n * The function is stateless, and does not change the AVCodecContext or the\n * device_ref AVHWDeviceContext.\n *\n * @param avctx The context which is currently calling get_format, and which\n *              implicitly contains all state needed for filling the returned\n *              AVHWFramesContext properly.\n * @param device_ref A reference to the AVHWDeviceContext describing the device\n *                   which will be used by the hardware decoder.\n * @param hw_pix_fmt The hwaccel format you are going to return from get_format.\n * @param out_frames_ref On success, set to a reference to an _uninitialized_\n *                       AVHWFramesContext, created from the given device_ref.\n *                       Fields will be set to values required for decoding.\n *                       Not changed if an error is returned.\n * @return zero on success, a negative value on error. The following error codes\n *         have special semantics:\n *      AVERROR(ENOENT): the decoder does not support this functionality. Setup\n *                       is always manual, or it is a decoder which does not\n *                       support setting AVCodecContext.hw_frames_ctx at all,\n *                       or it is a software format.\n *      AVERROR(EINVAL): it is known that hardware decoding is not supported for\n *                       this configuration, or the device_ref is not supported\n *                       for the hwaccel referenced by hw_pix_fmt.\n */\nint avcodec_get_hw_frames_parameters(AVCodecContext *avctx,\n                                     AVBufferRef *device_ref,\n                                     enum AVPixelFormat hw_pix_fmt,\n                                     AVBufferRef **out_frames_ref);\n\n\n\n/**\n * @defgroup lavc_parsing Frame parsing\n * @{\n */\n\nenum AVPictureStructure {\n    AV_PICTURE_STRUCTURE_UNKNOWN,      //< unknown\n    AV_PICTURE_STRUCTURE_TOP_FIELD,    //< coded as top field\n    AV_PICTURE_STRUCTURE_BOTTOM_FIELD, //< coded as bottom field\n    AV_PICTURE_STRUCTURE_FRAME,        //< coded as frame\n};\n\ntypedef struct AVCodecParserContext {\n    void *priv_data;\n    const struct AVCodecParser *parser;\n    int64_t frame_offset; /* offset of the current frame */\n    int64_t cur_offset; /* current offset\n                           (incremented by each av_parser_parse()) */\n    int64_t next_frame_offset; /* offset of the next frame */\n    /* video info */\n    int pict_type; /* XXX: Put it back in AVCodecContext. */\n    /**\n     * This field is used for proper frame duration computation in lavf.\n     * It signals, how much longer the frame duration of the current frame\n     * is compared to normal frame duration.\n     *\n     * frame_duration = (1 + repeat_pict) * time_base\n     *\n     * It is used by codecs like H.264 to display telecined material.\n     */\n    int repeat_pict; /* XXX: Put it back in AVCodecContext. */\n    int64_t pts;     /* pts of the current frame */\n    int64_t dts;     /* dts of the current frame */\n\n    /* private data */\n    int64_t last_pts;\n    int64_t last_dts;\n    int fetch_timestamp;\n\n#define AV_PARSER_PTS_NB 4\n    int cur_frame_start_index;\n    int64_t cur_frame_offset[AV_PARSER_PTS_NB];\n    int64_t cur_frame_pts[AV_PARSER_PTS_NB];\n    int64_t cur_frame_dts[AV_PARSER_PTS_NB];\n\n    int flags;\n#define PARSER_FLAG_COMPLETE_FRAMES           0x0001\n#define PARSER_FLAG_ONCE                      0x0002\n/// Set if the parser has a valid file offset\n#define PARSER_FLAG_FETCHED_OFFSET            0x0004\n#define PARSER_FLAG_USE_CODEC_TS              0x1000\n\n    int64_t offset;      ///< byte offset from starting packet start\n    int64_t cur_frame_end[AV_PARSER_PTS_NB];\n\n    /**\n     * Set by parser to 1 for key frames and 0 for non-key frames.\n     * It is initialized to -1, so if the parser doesn't set this flag,\n     * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames\n     * will be used.\n     */\n    int key_frame;\n\n    // Timestamp generation support:\n    /**\n     * Synchronization point for start of timestamp generation.\n     *\n     * Set to >0 for sync point, 0 for no sync point and <0 for undefined\n     * (default).\n     *\n     * For example, this corresponds to presence of H.264 buffering period\n     * SEI message.\n     */\n    int dts_sync_point;\n\n    /**\n     * Offset of the current timestamp against last timestamp sync point in\n     * units of AVCodecContext.time_base.\n     *\n     * Set to INT_MIN when dts_sync_point unused. Otherwise, it must\n     * contain a valid timestamp offset.\n     *\n     * Note that the timestamp of sync point has usually a nonzero\n     * dts_ref_dts_delta, which refers to the previous sync point. Offset of\n     * the next frame after timestamp sync point will be usually 1.\n     *\n     * For example, this corresponds to H.264 cpb_removal_delay.\n     */\n    int dts_ref_dts_delta;\n\n    /**\n     * Presentation delay of current frame in units of AVCodecContext.time_base.\n     *\n     * Set to INT_MIN when dts_sync_point unused. Otherwise, it must\n     * contain valid non-negative timestamp delta (presentation time of a frame\n     * must not lie in the past).\n     *\n     * This delay represents the difference between decoding and presentation\n     * time of the frame.\n     *\n     * For example, this corresponds to H.264 dpb_output_delay.\n     */\n    int pts_dts_delta;\n\n    /**\n     * Position of the packet in file.\n     *\n     * Analogous to cur_frame_pts/dts\n     */\n    int64_t cur_frame_pos[AV_PARSER_PTS_NB];\n\n    /**\n     * Byte position of currently parsed frame in stream.\n     */\n    int64_t pos;\n\n    /**\n     * Previous frame byte position.\n     */\n    int64_t last_pos;\n\n    /**\n     * Duration of the current frame.\n     * For audio, this is in units of 1 / AVCodecContext.sample_rate.\n     * For all other types, this is in units of AVCodecContext.time_base.\n     */\n    int duration;\n\n    enum AVFieldOrder field_order;\n\n    /**\n     * Indicate whether a picture is coded as a frame, top field or bottom field.\n     *\n     * For example, H.264 field_pic_flag equal to 0 corresponds to\n     * AV_PICTURE_STRUCTURE_FRAME. An H.264 picture with field_pic_flag\n     * equal to 1 and bottom_field_flag equal to 0 corresponds to\n     * AV_PICTURE_STRUCTURE_TOP_FIELD.\n     */\n    enum AVPictureStructure picture_structure;\n\n    /**\n     * Picture number incremented in presentation or output order.\n     * This field may be reinitialized at the first picture of a new sequence.\n     *\n     * For example, this corresponds to H.264 PicOrderCnt.\n     */\n    int output_picture_number;\n\n    /**\n     * Dimensions of the decoded video intended for presentation.\n     */\n    int width;\n    int height;\n\n    /**\n     * Dimensions of the coded video.\n     */\n    int coded_width;\n    int coded_height;\n\n    /**\n     * The format of the coded data, corresponds to enum AVPixelFormat for video\n     * and for enum AVSampleFormat for audio.\n     *\n     * Note that a decoder can have considerable freedom in how exactly it\n     * decodes the data, so the format reported here might be different from the\n     * one returned by a decoder.\n     */\n    int format;\n} AVCodecParserContext;\n\ntypedef struct AVCodecParser {\n    int codec_ids[7]; /* several codec IDs are permitted */\n    int priv_data_size;\n    int (*parser_init)(AVCodecParserContext *s);\n    /* This callback never returns an error, a negative value means that\n     * the frame start was in a previous packet. */\n    int (*parser_parse)(AVCodecParserContext *s,\n                        AVCodecContext *avctx,\n                        const uint8_t **poutbuf, int *poutbuf_size,\n                        const uint8_t *buf, int buf_size);\n    void (*parser_close)(AVCodecParserContext *s);\n    int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size);\n} AVCodecParser;\n\n/**\n * Iterate over all registered codec parsers.\n *\n * @param opaque a pointer where libavcodec will store the iteration state. Must\n *               point to NULL to start the iteration.\n *\n * @return the next registered codec parser or NULL when the iteration is\n *         finished\n */\nconst AVCodecParser *av_parser_iterate(void **opaque);\n\nAVCodecParserContext *av_parser_init(int codec_id);\n\n/**\n * Parse a packet.\n *\n * @param s             parser context.\n * @param avctx         codec context.\n * @param poutbuf       set to pointer to parsed buffer or NULL if not yet finished.\n * @param poutbuf_size  set to size of parsed buffer or zero if not yet finished.\n * @param buf           input buffer.\n * @param buf_size      buffer size in bytes without the padding. I.e. the full buffer\n                        size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE.\n                        To signal EOF, this should be 0 (so that the last frame\n                        can be output).\n * @param pts           input presentation timestamp.\n * @param dts           input decoding timestamp.\n * @param pos           input byte position in stream.\n * @return the number of bytes of the input bitstream used.\n *\n * Example:\n * @code\n *   while(in_len){\n *       len = av_parser_parse2(myparser, AVCodecContext, &data, &size,\n *                                        in_data, in_len,\n *                                        pts, dts, pos);\n *       in_data += len;\n *       in_len  -= len;\n *\n *       if(size)\n *          decode_frame(data, size);\n *   }\n * @endcode\n */\nint av_parser_parse2(AVCodecParserContext *s,\n                     AVCodecContext *avctx,\n                     uint8_t **poutbuf, int *poutbuf_size,\n                     const uint8_t *buf, int buf_size,\n                     int64_t pts, int64_t dts,\n                     int64_t pos);\n\nvoid av_parser_close(AVCodecParserContext *s);\n\n/**\n * @}\n * @}\n */\n\n/**\n * @addtogroup lavc_encoding\n * @{\n */\n\nint avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,\n                            const AVSubtitle *sub);\n\n\n/**\n * @}\n */\n\n/**\n * @defgroup lavc_misc Utility functions\n * @ingroup libavc\n *\n * Miscellaneous utility functions related to both encoding and decoding\n * (or neither).\n * @{\n */\n\n/**\n * @defgroup lavc_misc_pixfmt Pixel formats\n *\n * Functions for working with pixel formats.\n * @{\n */\n\n/**\n * Return a value representing the fourCC code associated to the\n * pixel format pix_fmt, or 0 if no associated fourCC code can be\n * found.\n */\nunsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt);\n\n/**\n * Find the best pixel format to convert to given a certain source pixel\n * format.  When converting from one pixel format to another, information loss\n * may occur.  For example, when converting from RGB24 to GRAY, the color\n * information will be lost. Similarly, other losses occur when converting from\n * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of\n * the given pixel formats should be used to suffer the least amount of loss.\n * The pixel formats from which it chooses one, are determined by the\n * pix_fmt_list parameter.\n *\n *\n * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from\n * @param[in] src_pix_fmt source pixel format\n * @param[in] has_alpha Whether the source pixel format alpha channel is used.\n * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur.\n * @return The best pixel format to convert to or -1 if none was found.\n */\nenum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list,\n                                            enum AVPixelFormat src_pix_fmt,\n                                            int has_alpha, int *loss_ptr);\n\nenum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt);\n\n/**\n * @}\n */\n\nvoid avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode);\n\nint avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size);\nint avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count);\n//FIXME func typedef\n\n/**\n * Fill AVFrame audio data and linesize pointers.\n *\n * The buffer buf must be a preallocated buffer with a size big enough\n * to contain the specified samples amount. The filled AVFrame data\n * pointers will point to this buffer.\n *\n * AVFrame extended_data channel pointers are allocated if necessary for\n * planar audio.\n *\n * @param frame       the AVFrame\n *                    frame->nb_samples must be set prior to calling the\n *                    function. This function fills in frame->data,\n *                    frame->extended_data, frame->linesize[0].\n * @param nb_channels channel count\n * @param sample_fmt  sample format\n * @param buf         buffer to use for frame data\n * @param buf_size    size of buffer\n * @param align       plane size sample alignment (0 = default)\n * @return            >=0 on success, negative error code on failure\n * @todo return the size in bytes required to store the samples in\n * case of success, at the next libavutil bump\n */\nint avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,\n                             enum AVSampleFormat sample_fmt, const uint8_t *buf,\n                             int buf_size, int align);\n\n/**\n * Reset the internal codec state / flush internal buffers. Should be called\n * e.g. when seeking or when switching to a different stream.\n *\n * @note for decoders, this function just releases any references the decoder\n * might keep internally, but the caller's references remain valid.\n *\n * @note for encoders, this function will only do something if the encoder\n * declares support for AV_CODEC_CAP_ENCODER_FLUSH. When called, the encoder\n * will drain any remaining packets, and can then be re-used for a different\n * stream (as opposed to sending a null frame which will leave the encoder\n * in a permanent EOF state after draining). This can be desirable if the\n * cost of tearing down and replacing the encoder instance is high.\n */\nvoid avcodec_flush_buffers(AVCodecContext *avctx);\n\n/**\n * Return audio frame duration.\n *\n * @param avctx        codec context\n * @param frame_bytes  size of the frame, or 0 if unknown\n * @return             frame duration, in samples, if known. 0 if not able to\n *                     determine.\n */\nint av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes);\n\n/* memory */\n\n/**\n * Same behaviour av_fast_malloc but the buffer has additional\n * AV_INPUT_BUFFER_PADDING_SIZE at the end which will always be 0.\n *\n * In addition the whole buffer will initially and after resizes\n * be 0-initialized so that no uninitialized data will ever appear.\n */\nvoid av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size);\n\n/**\n * Same behaviour av_fast_padded_malloc except that buffer will always\n * be 0-initialized after call.\n */\nvoid av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size);\n\n/**\n * @return a positive value if s is open (i.e. avcodec_open2() was called on it\n * with no corresponding avcodec_close()), 0 otherwise.\n */\nint avcodec_is_open(AVCodecContext *s);\n\n/**\n * @}\n */\n\n#endif /* AVCODEC_AVCODEC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/avdct.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_AVDCT_H\n#define AVCODEC_AVDCT_H\n\n#include \"libavutil/opt.h\"\n\n/**\n * AVDCT context.\n * @note function pointers can be NULL if the specific features have been\n *       disabled at build time.\n */\ntypedef struct AVDCT {\n    const AVClass *av_class;\n\n    void (*idct)(int16_t *block /* align 16 */);\n\n    /**\n     * IDCT input permutation.\n     * Several optimized IDCTs need a permutated input (relative to the\n     * normal order of the reference IDCT).\n     * This permutation must be performed before the idct_put/add.\n     * Note, normally this can be merged with the zigzag/alternate scan<br>\n     * An example to avoid confusion:\n     * - (->decode coeffs -> zigzag reorder -> dequant -> reference IDCT -> ...)\n     * - (x -> reference DCT -> reference IDCT -> x)\n     * - (x -> reference DCT -> simple_mmx_perm = idct_permutation\n     *    -> simple_idct_mmx -> x)\n     * - (-> decode coeffs -> zigzag reorder -> simple_mmx_perm -> dequant\n     *    -> simple_idct_mmx -> ...)\n     */\n    uint8_t idct_permutation[64];\n\n    void (*fdct)(int16_t *block /* align 16 */);\n\n\n    /**\n     * DCT algorithm.\n     * must use AVOptions to set this field.\n     */\n    int dct_algo;\n\n    /**\n     * IDCT algorithm.\n     * must use AVOptions to set this field.\n     */\n    int idct_algo;\n\n    void (*get_pixels)(int16_t *block /* align 16 */,\n                       const uint8_t *pixels /* align 8 */,\n                       ptrdiff_t line_size);\n\n    int bits_per_sample;\n\n    void (*get_pixels_unaligned)(int16_t *block /* align 16 */,\n                       const uint8_t *pixels,\n                       ptrdiff_t line_size);\n} AVDCT;\n\n/**\n * Allocates a AVDCT context.\n * This needs to be initialized with avcodec_dct_init() after optionally\n * configuring it with AVOptions.\n *\n * To free it use av_free()\n */\nAVDCT *avcodec_dct_alloc(void);\nint avcodec_dct_init(AVDCT *);\n\nconst AVClass *avcodec_dct_get_class(void);\n\n#endif /* AVCODEC_AVDCT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/avfft.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_AVFFT_H\n#define AVCODEC_AVFFT_H\n\n/**\n * @file\n * @ingroup lavc_fft\n * FFT functions\n */\n\n/**\n * @defgroup lavc_fft FFT functions\n * @ingroup lavc_misc\n *\n * @{\n */\n\ntypedef float FFTSample;\n\ntypedef struct FFTComplex {\n    FFTSample re, im;\n} FFTComplex;\n\ntypedef struct FFTContext FFTContext;\n\n/**\n * Set up a complex FFT.\n * @param nbits           log2 of the length of the input array\n * @param inverse         if 0 perform the forward transform, if 1 perform the inverse\n */\nFFTContext *av_fft_init(int nbits, int inverse);\n\n/**\n * Do the permutation needed BEFORE calling ff_fft_calc().\n */\nvoid av_fft_permute(FFTContext *s, FFTComplex *z);\n\n/**\n * Do a complex FFT with the parameters defined in av_fft_init(). The\n * input data must be permuted before. No 1.0/sqrt(n) normalization is done.\n */\nvoid av_fft_calc(FFTContext *s, FFTComplex *z);\n\nvoid av_fft_end(FFTContext *s);\n\nFFTContext *av_mdct_init(int nbits, int inverse, double scale);\nvoid av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);\nvoid av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input);\nvoid av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);\nvoid av_mdct_end(FFTContext *s);\n\n/* Real Discrete Fourier Transform */\n\nenum RDFTransformType {\n    DFT_R2C,\n    IDFT_C2R,\n    IDFT_R2C,\n    DFT_C2R,\n};\n\ntypedef struct RDFTContext RDFTContext;\n\n/**\n * Set up a real FFT.\n * @param nbits           log2 of the length of the input array\n * @param trans           the type of transform\n */\nRDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans);\nvoid av_rdft_calc(RDFTContext *s, FFTSample *data);\nvoid av_rdft_end(RDFTContext *s);\n\n/* Discrete Cosine Transform */\n\ntypedef struct DCTContext DCTContext;\n\nenum DCTTransformType {\n    DCT_II = 0,\n    DCT_III,\n    DCT_I,\n    DST_I,\n};\n\n/**\n * Set up DCT.\n *\n * @param nbits           size of the input array:\n *                        (1 << nbits)     for DCT-II, DCT-III and DST-I\n *                        (1 << nbits) + 1 for DCT-I\n * @param type            the type of transform\n *\n * @note the first element of the input of DST-I is ignored\n */\nDCTContext *av_dct_init(int nbits, enum DCTTransformType type);\nvoid av_dct_calc(DCTContext *s, FFTSample *data);\nvoid av_dct_end (DCTContext *s);\n\n/**\n * @}\n */\n\n#endif /* AVCODEC_AVFFT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/bsf.h",
    "content": "/*\n * Bitstream filters public API\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_BSF_H\n#define AVCODEC_BSF_H\n\n#include \"libavutil/dict.h\"\n#include \"libavutil/log.h\"\n#include \"libavutil/rational.h\"\n\n#include \"codec_id.h\"\n#include \"codec_par.h\"\n#include \"packet.h\"\n\n/**\n * @defgroup lavc_bsf Bitstream filters\n * @ingroup libavc\n *\n * Bitstream filters transform encoded media data without decoding it. This\n * allows e.g. manipulating various header values. Bitstream filters operate on\n * @ref AVPacket \"AVPackets\".\n *\n * The bitstream filtering API is centered around two structures:\n * AVBitStreamFilter and AVBSFContext. The former represents a bitstream filter\n * in abstract, the latter a specific filtering process. Obtain an\n * AVBitStreamFilter using av_bsf_get_by_name() or av_bsf_iterate(), then pass\n * it to av_bsf_alloc() to create an AVBSFContext. Fill in the user-settable\n * AVBSFContext fields, as described in its documentation, then call\n * av_bsf_init() to prepare the filter context for use.\n *\n * Submit packets for filtering using av_bsf_send_packet(), obtain filtered\n * results with av_bsf_receive_packet(). When no more input packets will be\n * sent, submit a NULL AVPacket to signal the end of the stream to the filter.\n * av_bsf_receive_packet() will then return trailing packets, if any are\n * produced by the filter.\n *\n * Finally, free the filter context with av_bsf_free().\n * @{\n */\n\n/**\n * The bitstream filter state.\n *\n * This struct must be allocated with av_bsf_alloc() and freed with\n * av_bsf_free().\n *\n * The fields in the struct will only be changed (by the caller or by the\n * filter) as described in their documentation, and are to be considered\n * immutable otherwise.\n */\ntypedef struct AVBSFContext {\n    /**\n     * A class for logging and AVOptions\n     */\n    const AVClass *av_class;\n\n    /**\n     * The bitstream filter this context is an instance of.\n     */\n    const struct AVBitStreamFilter *filter;\n\n    /**\n     * Opaque filter-specific private data. If filter->priv_class is non-NULL,\n     * this is an AVOptions-enabled struct.\n     */\n    void *priv_data;\n\n    /**\n     * Parameters of the input stream. This field is allocated in\n     * av_bsf_alloc(), it needs to be filled by the caller before\n     * av_bsf_init().\n     */\n    AVCodecParameters *par_in;\n\n    /**\n     * Parameters of the output stream. This field is allocated in\n     * av_bsf_alloc(), it is set by the filter in av_bsf_init().\n     */\n    AVCodecParameters *par_out;\n\n    /**\n     * The timebase used for the timestamps of the input packets. Set by the\n     * caller before av_bsf_init().\n     */\n    AVRational time_base_in;\n\n    /**\n     * The timebase used for the timestamps of the output packets. Set by the\n     * filter in av_bsf_init().\n     */\n    AVRational time_base_out;\n} AVBSFContext;\n\ntypedef struct AVBitStreamFilter {\n    const char *name;\n\n    /**\n     * A list of codec ids supported by the filter, terminated by\n     * AV_CODEC_ID_NONE.\n     * May be NULL, in that case the bitstream filter works with any codec id.\n     */\n    const enum AVCodecID *codec_ids;\n\n    /**\n     * A class for the private data, used to declare bitstream filter private\n     * AVOptions. This field is NULL for bitstream filters that do not declare\n     * any options.\n     *\n     * If this field is non-NULL, the first member of the filter private data\n     * must be a pointer to AVClass, which will be set by libavcodec generic\n     * code to this class.\n     */\n    const AVClass *priv_class;\n} AVBitStreamFilter;\n\n/**\n * @return a bitstream filter with the specified name or NULL if no such\n *         bitstream filter exists.\n */\nconst AVBitStreamFilter *av_bsf_get_by_name(const char *name);\n\n/**\n * Iterate over all registered bitstream filters.\n *\n * @param opaque a pointer where libavcodec will store the iteration state. Must\n *               point to NULL to start the iteration.\n *\n * @return the next registered bitstream filter or NULL when the iteration is\n *         finished\n */\nconst AVBitStreamFilter *av_bsf_iterate(void **opaque);\n\n/**\n * Allocate a context for a given bitstream filter. The caller must fill in the\n * context parameters as described in the documentation and then call\n * av_bsf_init() before sending any data to the filter.\n *\n * @param filter the filter for which to allocate an instance.\n * @param[out] ctx a pointer into which the pointer to the newly-allocated context\n *                 will be written. It must be freed with av_bsf_free() after the\n *                 filtering is done.\n *\n * @return 0 on success, a negative AVERROR code on failure\n */\nint av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx);\n\n/**\n * Prepare the filter for use, after all the parameters and options have been\n * set.\n */\nint av_bsf_init(AVBSFContext *ctx);\n\n/**\n * Submit a packet for filtering.\n *\n * After sending each packet, the filter must be completely drained by calling\n * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or\n * AVERROR_EOF.\n *\n * @param pkt the packet to filter. The bitstream filter will take ownership of\n * the packet and reset the contents of pkt. pkt is not touched if an error occurs.\n * If pkt is empty (i.e. NULL, or pkt->data is NULL and pkt->side_data_elems zero),\n * it signals the end of the stream (i.e. no more non-empty packets will be sent;\n * sending more empty packets does nothing) and will cause the filter to output\n * any packets it may have buffered internally.\n *\n * @return\n *  - 0 on success.\n *  - AVERROR(EAGAIN) if packets need to be retrieved from the filter (using\n *    av_bsf_receive_packet()) before new input can be consumed.\n *  - Another negative AVERROR value if an error occurs.\n */\nint av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt);\n\n/**\n * Retrieve a filtered packet.\n *\n * @param[out] pkt this struct will be filled with the contents of the filtered\n *                 packet. It is owned by the caller and must be freed using\n *                 av_packet_unref() when it is no longer needed.\n *                 This parameter should be \"clean\" (i.e. freshly allocated\n *                 with av_packet_alloc() or unreffed with av_packet_unref())\n *                 when this function is called. If this function returns\n *                 successfully, the contents of pkt will be completely\n *                 overwritten by the returned data. On failure, pkt is not\n *                 touched.\n *\n * @return\n *  - 0 on success.\n *  - AVERROR(EAGAIN) if more packets need to be sent to the filter (using\n *    av_bsf_send_packet()) to get more output.\n *  - AVERROR_EOF if there will be no further output from the filter.\n *  - Another negative AVERROR value if an error occurs.\n *\n * @note one input packet may result in several output packets, so after sending\n * a packet with av_bsf_send_packet(), this function needs to be called\n * repeatedly until it stops returning 0. It is also possible for a filter to\n * output fewer packets than were sent to it, so this function may return\n * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call.\n */\nint av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt);\n\n/**\n * Reset the internal bitstream filter state. Should be called e.g. when seeking.\n */\nvoid av_bsf_flush(AVBSFContext *ctx);\n\n/**\n * Free a bitstream filter context and everything associated with it; write NULL\n * into the supplied pointer.\n */\nvoid av_bsf_free(AVBSFContext **ctx);\n\n/**\n * Get the AVClass for AVBSFContext. It can be used in combination with\n * AV_OPT_SEARCH_FAKE_OBJ for examining options.\n *\n * @see av_opt_find().\n */\nconst AVClass *av_bsf_get_class(void);\n\n/**\n * Structure for chain/list of bitstream filters.\n * Empty list can be allocated by av_bsf_list_alloc().\n */\ntypedef struct AVBSFList AVBSFList;\n\n/**\n * Allocate empty list of bitstream filters.\n * The list must be later freed by av_bsf_list_free()\n * or finalized by av_bsf_list_finalize().\n *\n * @return Pointer to @ref AVBSFList on success, NULL in case of failure\n */\nAVBSFList *av_bsf_list_alloc(void);\n\n/**\n * Free list of bitstream filters.\n *\n * @param lst Pointer to pointer returned by av_bsf_list_alloc()\n */\nvoid av_bsf_list_free(AVBSFList **lst);\n\n/**\n * Append bitstream filter to the list of bitstream filters.\n *\n * @param lst List to append to\n * @param bsf Filter context to be appended\n *\n * @return >=0 on success, negative AVERROR in case of failure\n */\nint av_bsf_list_append(AVBSFList *lst, AVBSFContext *bsf);\n\n/**\n * Construct new bitstream filter context given it's name and options\n * and append it to the list of bitstream filters.\n *\n * @param lst      List to append to\n * @param bsf_name Name of the bitstream filter\n * @param options  Options for the bitstream filter, can be set to NULL\n *\n * @return >=0 on success, negative AVERROR in case of failure\n */\nint av_bsf_list_append2(AVBSFList *lst, const char * bsf_name, AVDictionary **options);\n/**\n * Finalize list of bitstream filters.\n *\n * This function will transform @ref AVBSFList to single @ref AVBSFContext,\n * so the whole chain of bitstream filters can be treated as single filter\n * freshly allocated by av_bsf_alloc().\n * If the call is successful, @ref AVBSFList structure is freed and lst\n * will be set to NULL. In case of failure, caller is responsible for\n * freeing the structure by av_bsf_list_free()\n *\n * @param      lst Filter list structure to be transformed\n * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure\n *                 representing the chain of bitstream filters\n *\n * @return >=0 on success, negative AVERROR in case of failure\n */\nint av_bsf_list_finalize(AVBSFList **lst, AVBSFContext **bsf);\n\n/**\n * Parse string describing list of bitstream filters and create single\n * @ref AVBSFContext describing the whole chain of bitstream filters.\n * Resulting @ref AVBSFContext can be treated as any other @ref AVBSFContext freshly\n * allocated by av_bsf_alloc().\n *\n * @param      str String describing chain of bitstream filters in format\n *                 `bsf1[=opt1=val1:opt2=val2][,bsf2]`\n * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure\n *                 representing the chain of bitstream filters\n *\n * @return >=0 on success, negative AVERROR in case of failure\n */\nint av_bsf_list_parse_str(const char *str, AVBSFContext **bsf);\n\n/**\n * Get null/pass-through bitstream filter.\n *\n * @param[out] bsf Pointer to be set to new instance of pass-through bitstream filter\n *\n * @return\n */\nint av_bsf_get_null_filter(AVBSFContext **bsf);\n\n/**\n * @}\n */\n\n#endif // AVCODEC_BSF_H\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/codec.h",
    "content": "/*\n * AVCodec public API\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_CODEC_H\n#define AVCODEC_CODEC_H\n\n#include <stdint.h>\n\n#include \"libavutil/avutil.h\"\n#include \"libavutil/hwcontext.h\"\n#include \"libavutil/log.h\"\n#include \"libavutil/pixfmt.h\"\n#include \"libavutil/rational.h\"\n#include \"libavutil/samplefmt.h\"\n\n#include \"libavcodec/codec_id.h\"\n#include \"libavcodec/version_major.h\"\n\n/**\n * @addtogroup lavc_core\n * @{\n */\n\n/**\n * Decoder can use draw_horiz_band callback.\n */\n#define AV_CODEC_CAP_DRAW_HORIZ_BAND     (1 <<  0)\n/**\n * Codec uses get_buffer() or get_encode_buffer() for allocating buffers and\n * supports custom allocators.\n * If not set, it might not use get_buffer() or get_encode_buffer() at all, or\n * use operations that assume the buffer was allocated by\n * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer.\n */\n#define AV_CODEC_CAP_DR1                 (1 <<  1)\n#if FF_API_FLAG_TRUNCATED\n/**\n * @deprecated Use parsers to always send proper frames.\n */\n#define AV_CODEC_CAP_TRUNCATED           (1 <<  3)\n#endif\n/**\n * Encoder or decoder requires flushing with NULL input at the end in order to\n * give the complete and correct output.\n *\n * NOTE: If this flag is not set, the codec is guaranteed to never be fed with\n *       with NULL data. The user can still send NULL data to the public encode\n *       or decode function, but libavcodec will not pass it along to the codec\n *       unless this flag is set.\n *\n * Decoders:\n * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL,\n * avpkt->size=0 at the end to get the delayed data until the decoder no longer\n * returns frames.\n *\n * Encoders:\n * The encoder needs to be fed with NULL data at the end of encoding until the\n * encoder no longer returns data.\n *\n * NOTE: For encoders implementing the AVCodec.encode2() function, setting this\n *       flag also means that the encoder must set the pts and duration for\n *       each output packet. If this flag is not set, the pts and duration will\n *       be determined by libavcodec from the input frame.\n */\n#define AV_CODEC_CAP_DELAY               (1 <<  5)\n/**\n * Codec can be fed a final frame with a smaller size.\n * This can be used to prevent truncation of the last audio samples.\n */\n#define AV_CODEC_CAP_SMALL_LAST_FRAME    (1 <<  6)\n\n/**\n * Codec can output multiple frames per AVPacket\n * Normally demuxers return one frame at a time, demuxers which do not do\n * are connected to a parser to split what they return into proper frames.\n * This flag is reserved to the very rare category of codecs which have a\n * bitstream that cannot be split into frames without timeconsuming\n * operations like full decoding. Demuxers carrying such bitstreams thus\n * may return multiple frames in a packet. This has many disadvantages like\n * prohibiting stream copy in many cases thus it should only be considered\n * as a last resort.\n */\n#define AV_CODEC_CAP_SUBFRAMES           (1 <<  8)\n/**\n * Codec is experimental and is thus avoided in favor of non experimental\n * encoders\n */\n#define AV_CODEC_CAP_EXPERIMENTAL        (1 <<  9)\n/**\n * Codec should fill in channel configuration and samplerate instead of container\n */\n#define AV_CODEC_CAP_CHANNEL_CONF        (1 << 10)\n/**\n * Codec supports frame-level multithreading.\n */\n#define AV_CODEC_CAP_FRAME_THREADS       (1 << 12)\n/**\n * Codec supports slice-based (or partition-based) multithreading.\n */\n#define AV_CODEC_CAP_SLICE_THREADS       (1 << 13)\n/**\n * Codec supports changed parameters at any point.\n */\n#define AV_CODEC_CAP_PARAM_CHANGE        (1 << 14)\n/**\n * Codec supports multithreading through a method other than slice- or\n * frame-level multithreading. Typically this marks wrappers around\n * multithreading-capable external libraries.\n */\n#define AV_CODEC_CAP_OTHER_THREADS       (1 << 15)\n#if FF_API_AUTO_THREADS\n#define AV_CODEC_CAP_AUTO_THREADS        AV_CODEC_CAP_OTHER_THREADS\n#endif\n/**\n * Audio encoder supports receiving a different number of samples in each call.\n */\n#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16)\n/**\n * Decoder is not a preferred choice for probing.\n * This indicates that the decoder is not a good choice for probing.\n * It could for example be an expensive to spin up hardware decoder,\n * or it could simply not provide a lot of useful information about\n * the stream.\n * A decoder marked with this flag should only be used as last resort\n * choice for probing.\n */\n#define AV_CODEC_CAP_AVOID_PROBING       (1 << 17)\n\n#if FF_API_UNUSED_CODEC_CAPS\n/**\n * Deprecated and unused. Use AVCodecDescriptor.props instead\n */\n#define AV_CODEC_CAP_INTRA_ONLY       0x40000000\n/**\n * Deprecated and unused. Use AVCodecDescriptor.props instead\n */\n#define AV_CODEC_CAP_LOSSLESS         0x80000000\n#endif\n\n/**\n * Codec is backed by a hardware implementation. Typically used to\n * identify a non-hwaccel hardware decoder. For information about hwaccels, use\n * avcodec_get_hw_config() instead.\n */\n#define AV_CODEC_CAP_HARDWARE            (1 << 18)\n\n/**\n * Codec is potentially backed by a hardware implementation, but not\n * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the\n * implementation provides some sort of internal fallback.\n */\n#define AV_CODEC_CAP_HYBRID              (1 << 19)\n\n/**\n * This codec takes the reordered_opaque field from input AVFrames\n * and returns it in the corresponding field in AVCodecContext after\n * encoding.\n */\n#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20)\n\n/**\n * This encoder can be flushed using avcodec_flush_buffers(). If this flag is\n * not set, the encoder must be closed and reopened to ensure that no frames\n * remain pending.\n */\n#define AV_CODEC_CAP_ENCODER_FLUSH   (1 << 21)\n\n/**\n * AVProfile.\n */\ntypedef struct AVProfile {\n    int profile;\n    const char *name; ///< short name for the profile\n} AVProfile;\n\n/**\n * AVCodec.\n */\ntypedef struct AVCodec {\n    /**\n     * Name of the codec implementation.\n     * The name is globally unique among encoders and among decoders (but an\n     * encoder and a decoder can share the same name).\n     * This is the primary way to find a codec from the user perspective.\n     */\n    const char *name;\n    /**\n     * Descriptive name for the codec, meant to be more human readable than name.\n     * You should use the NULL_IF_CONFIG_SMALL() macro to define it.\n     */\n    const char *long_name;\n    enum AVMediaType type;\n    enum AVCodecID id;\n    /**\n     * Codec capabilities.\n     * see AV_CODEC_CAP_*\n     */\n    int capabilities;\n    uint8_t max_lowres;                     ///< maximum value for lowres supported by the decoder\n    const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}\n    const enum AVPixelFormat *pix_fmts;     ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1\n    const int *supported_samplerates;       ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0\n    const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * @deprecated use ch_layouts instead\n     */\n    attribute_deprecated\n    const uint64_t *channel_layouts;         ///< array of support channel layouts, or NULL if unknown. array is terminated by 0\n#endif\n    const AVClass *priv_class;              ///< AVClass for the private context\n    const AVProfile *profiles;              ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}\n\n    /**\n     * Group name of the codec implementation.\n     * This is a short symbolic name of the wrapper backing this codec. A\n     * wrapper uses some kind of external implementation for the codec, such\n     * as an external library, or a codec implementation provided by the OS or\n     * the hardware.\n     * If this field is NULL, this is a builtin, libavcodec native codec.\n     * If non-NULL, this will be the suffix in AVCodec.name in most cases\n     * (usually AVCodec.name will be of the form \"<codec_name>_<wrapper_name>\").\n     */\n    const char *wrapper_name;\n\n    /**\n     * Array of supported channel layouts, terminated with a zeroed layout.\n     */\n    const AVChannelLayout *ch_layouts;\n} AVCodec;\n\n/**\n * Iterate over all registered codecs.\n *\n * @param opaque a pointer where libavcodec will store the iteration state. Must\n *               point to NULL to start the iteration.\n *\n * @return the next registered codec or NULL when the iteration is\n *         finished\n */\nconst AVCodec *av_codec_iterate(void **opaque);\n\n/**\n * Find a registered decoder with a matching codec ID.\n *\n * @param id AVCodecID of the requested decoder\n * @return A decoder if one was found, NULL otherwise.\n */\nconst AVCodec *avcodec_find_decoder(enum AVCodecID id);\n\n/**\n * Find a registered decoder with the specified name.\n *\n * @param name name of the requested decoder\n * @return A decoder if one was found, NULL otherwise.\n */\nconst AVCodec *avcodec_find_decoder_by_name(const char *name);\n\n/**\n * Find a registered encoder with a matching codec ID.\n *\n * @param id AVCodecID of the requested encoder\n * @return An encoder if one was found, NULL otherwise.\n */\nconst AVCodec *avcodec_find_encoder(enum AVCodecID id);\n\n/**\n * Find a registered encoder with the specified name.\n *\n * @param name name of the requested encoder\n * @return An encoder if one was found, NULL otherwise.\n */\nconst AVCodec *avcodec_find_encoder_by_name(const char *name);\n/**\n * @return a non-zero number if codec is an encoder, zero otherwise\n */\nint av_codec_is_encoder(const AVCodec *codec);\n\n/**\n * @return a non-zero number if codec is a decoder, zero otherwise\n */\nint av_codec_is_decoder(const AVCodec *codec);\n\n/**\n * Return a name for the specified profile, if available.\n *\n * @param codec the codec that is searched for the given profile\n * @param profile the profile value for which a name is requested\n * @return A name for the profile if found, NULL otherwise.\n */\nconst char *av_get_profile_name(const AVCodec *codec, int profile);\n\nenum {\n    /**\n     * The codec supports this format via the hw_device_ctx interface.\n     *\n     * When selecting this format, AVCodecContext.hw_device_ctx should\n     * have been set to a device of the specified type before calling\n     * avcodec_open2().\n     */\n    AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01,\n    /**\n     * The codec supports this format via the hw_frames_ctx interface.\n     *\n     * When selecting this format for a decoder,\n     * AVCodecContext.hw_frames_ctx should be set to a suitable frames\n     * context inside the get_format() callback.  The frames context\n     * must have been created on a device of the specified type.\n     *\n     * When selecting this format for an encoder,\n     * AVCodecContext.hw_frames_ctx should be set to the context which\n     * will be used for the input frames before calling avcodec_open2().\n     */\n    AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02,\n    /**\n     * The codec supports this format by some internal method.\n     *\n     * This format can be selected without any additional configuration -\n     * no device or frames context is required.\n     */\n    AV_CODEC_HW_CONFIG_METHOD_INTERNAL      = 0x04,\n    /**\n     * The codec supports this format by some ad-hoc method.\n     *\n     * Additional settings and/or function calls are required.  See the\n     * codec-specific documentation for details.  (Methods requiring\n     * this sort of configuration are deprecated and others should be\n     * used in preference.)\n     */\n    AV_CODEC_HW_CONFIG_METHOD_AD_HOC        = 0x08,\n};\n\ntypedef struct AVCodecHWConfig {\n    /**\n     * For decoders, a hardware pixel format which that decoder may be\n     * able to decode to if suitable hardware is available.\n     *\n     * For encoders, a pixel format which the encoder may be able to\n     * accept.  If set to AV_PIX_FMT_NONE, this applies to all pixel\n     * formats supported by the codec.\n     */\n    enum AVPixelFormat pix_fmt;\n    /**\n     * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible\n     * setup methods which can be used with this configuration.\n     */\n    int methods;\n    /**\n     * The device type associated with the configuration.\n     *\n     * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and\n     * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused.\n     */\n    enum AVHWDeviceType device_type;\n} AVCodecHWConfig;\n\n/**\n * Retrieve supported hardware configurations for a codec.\n *\n * Values of index from zero to some maximum return the indexed configuration\n * descriptor; all other values return NULL.  If the codec does not support\n * any hardware configurations then it will always return NULL.\n */\nconst AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index);\n\n/**\n * @}\n */\n\n#endif /* AVCODEC_CODEC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/codec_desc.h",
    "content": "/*\n * Codec descriptors public API\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_CODEC_DESC_H\n#define AVCODEC_CODEC_DESC_H\n\n#include \"libavutil/avutil.h\"\n\n#include \"codec_id.h\"\n\n/**\n * @addtogroup lavc_core\n * @{\n */\n\n/**\n * This struct describes the properties of a single codec described by an\n * AVCodecID.\n * @see avcodec_descriptor_get()\n */\ntypedef struct AVCodecDescriptor {\n    enum AVCodecID     id;\n    enum AVMediaType type;\n    /**\n     * Name of the codec described by this descriptor. It is non-empty and\n     * unique for each codec descriptor. It should contain alphanumeric\n     * characters and '_' only.\n     */\n    const char      *name;\n    /**\n     * A more descriptive name for this codec. May be NULL.\n     */\n    const char *long_name;\n    /**\n     * Codec properties, a combination of AV_CODEC_PROP_* flags.\n     */\n    int             props;\n    /**\n     * MIME type(s) associated with the codec.\n     * May be NULL; if not, a NULL-terminated array of MIME types.\n     * The first item is always non-NULL and is the preferred MIME type.\n     */\n    const char *const *mime_types;\n    /**\n     * If non-NULL, an array of profiles recognized for this codec.\n     * Terminated with FF_PROFILE_UNKNOWN.\n     */\n    const struct AVProfile *profiles;\n} AVCodecDescriptor;\n\n/**\n * Codec uses only intra compression.\n * Video and audio codecs only.\n */\n#define AV_CODEC_PROP_INTRA_ONLY    (1 << 0)\n/**\n * Codec supports lossy compression. Audio and video codecs only.\n * @note a codec may support both lossy and lossless\n * compression modes\n */\n#define AV_CODEC_PROP_LOSSY         (1 << 1)\n/**\n * Codec supports lossless compression. Audio and video codecs only.\n */\n#define AV_CODEC_PROP_LOSSLESS      (1 << 2)\n/**\n * Codec supports frame reordering. That is, the coded order (the order in which\n * the encoded packets are output by the encoders / stored / input to the\n * decoders) may be different from the presentation order of the corresponding\n * frames.\n *\n * For codecs that do not have this property set, PTS and DTS should always be\n * equal.\n */\n#define AV_CODEC_PROP_REORDER       (1 << 3)\n/**\n * Subtitle codec is bitmap based\n * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field.\n */\n#define AV_CODEC_PROP_BITMAP_SUB    (1 << 16)\n/**\n * Subtitle codec is text based.\n * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field.\n */\n#define AV_CODEC_PROP_TEXT_SUB      (1 << 17)\n\n/**\n * @return descriptor for given codec ID or NULL if no descriptor exists.\n */\nconst AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id);\n\n/**\n * Iterate over all codec descriptors known to libavcodec.\n *\n * @param prev previous descriptor. NULL to get the first descriptor.\n *\n * @return next descriptor or NULL after the last descriptor\n */\nconst AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev);\n\n/**\n * @return codec descriptor with the given name or NULL if no such descriptor\n *         exists.\n */\nconst AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name);\n\n/**\n * @}\n */\n\n#endif // AVCODEC_CODEC_DESC_H\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/codec_id.h",
    "content": "/*\n * Codec IDs\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_CODEC_ID_H\n#define AVCODEC_CODEC_ID_H\n\n#include \"libavutil/avutil.h\"\n#include \"libavutil/samplefmt.h\"\n\n/**\n * @addtogroup lavc_core\n * @{\n */\n\n/**\n * Identify the syntax and semantics of the bitstream.\n * The principle is roughly:\n * Two decoders with the same ID can decode the same streams.\n * Two encoders with the same ID can encode compatible streams.\n * There may be slight deviations from the principle due to implementation\n * details.\n *\n * If you add a codec ID to this list, add it so that\n * 1. no value of an existing codec ID changes (that would break ABI),\n * 2. it is as close as possible to similar codecs\n *\n * After adding new codec IDs, do not forget to add an entry to the codec\n * descriptor list and bump libavcodec minor version.\n */\nenum AVCodecID {\n    AV_CODEC_ID_NONE,\n\n    /* video codecs */\n    AV_CODEC_ID_MPEG1VIDEO,\n    AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding\n    AV_CODEC_ID_H261,\n    AV_CODEC_ID_H263,\n    AV_CODEC_ID_RV10,\n    AV_CODEC_ID_RV20,\n    AV_CODEC_ID_MJPEG,\n    AV_CODEC_ID_MJPEGB,\n    AV_CODEC_ID_LJPEG,\n    AV_CODEC_ID_SP5X,\n    AV_CODEC_ID_JPEGLS,\n    AV_CODEC_ID_MPEG4,\n    AV_CODEC_ID_RAWVIDEO,\n    AV_CODEC_ID_MSMPEG4V1,\n    AV_CODEC_ID_MSMPEG4V2,\n    AV_CODEC_ID_MSMPEG4V3,\n    AV_CODEC_ID_WMV1,\n    AV_CODEC_ID_WMV2,\n    AV_CODEC_ID_H263P,\n    AV_CODEC_ID_H263I,\n    AV_CODEC_ID_FLV1,\n    AV_CODEC_ID_SVQ1,\n    AV_CODEC_ID_SVQ3,\n    AV_CODEC_ID_DVVIDEO,\n    AV_CODEC_ID_HUFFYUV,\n    AV_CODEC_ID_CYUV,\n    AV_CODEC_ID_H264,\n    AV_CODEC_ID_INDEO3,\n    AV_CODEC_ID_VP3,\n    AV_CODEC_ID_THEORA,\n    AV_CODEC_ID_ASV1,\n    AV_CODEC_ID_ASV2,\n    AV_CODEC_ID_FFV1,\n    AV_CODEC_ID_4XM,\n    AV_CODEC_ID_VCR1,\n    AV_CODEC_ID_CLJR,\n    AV_CODEC_ID_MDEC,\n    AV_CODEC_ID_ROQ,\n    AV_CODEC_ID_INTERPLAY_VIDEO,\n    AV_CODEC_ID_XAN_WC3,\n    AV_CODEC_ID_XAN_WC4,\n    AV_CODEC_ID_RPZA,\n    AV_CODEC_ID_CINEPAK,\n    AV_CODEC_ID_WS_VQA,\n    AV_CODEC_ID_MSRLE,\n    AV_CODEC_ID_MSVIDEO1,\n    AV_CODEC_ID_IDCIN,\n    AV_CODEC_ID_8BPS,\n    AV_CODEC_ID_SMC,\n    AV_CODEC_ID_FLIC,\n    AV_CODEC_ID_TRUEMOTION1,\n    AV_CODEC_ID_VMDVIDEO,\n    AV_CODEC_ID_MSZH,\n    AV_CODEC_ID_ZLIB,\n    AV_CODEC_ID_QTRLE,\n    AV_CODEC_ID_TSCC,\n    AV_CODEC_ID_ULTI,\n    AV_CODEC_ID_QDRAW,\n    AV_CODEC_ID_VIXL,\n    AV_CODEC_ID_QPEG,\n    AV_CODEC_ID_PNG,\n    AV_CODEC_ID_PPM,\n    AV_CODEC_ID_PBM,\n    AV_CODEC_ID_PGM,\n    AV_CODEC_ID_PGMYUV,\n    AV_CODEC_ID_PAM,\n    AV_CODEC_ID_FFVHUFF,\n    AV_CODEC_ID_RV30,\n    AV_CODEC_ID_RV40,\n    AV_CODEC_ID_VC1,\n    AV_CODEC_ID_WMV3,\n    AV_CODEC_ID_LOCO,\n    AV_CODEC_ID_WNV1,\n    AV_CODEC_ID_AASC,\n    AV_CODEC_ID_INDEO2,\n    AV_CODEC_ID_FRAPS,\n    AV_CODEC_ID_TRUEMOTION2,\n    AV_CODEC_ID_BMP,\n    AV_CODEC_ID_CSCD,\n    AV_CODEC_ID_MMVIDEO,\n    AV_CODEC_ID_ZMBV,\n    AV_CODEC_ID_AVS,\n    AV_CODEC_ID_SMACKVIDEO,\n    AV_CODEC_ID_NUV,\n    AV_CODEC_ID_KMVC,\n    AV_CODEC_ID_FLASHSV,\n    AV_CODEC_ID_CAVS,\n    AV_CODEC_ID_JPEG2000,\n    AV_CODEC_ID_VMNC,\n    AV_CODEC_ID_VP5,\n    AV_CODEC_ID_VP6,\n    AV_CODEC_ID_VP6F,\n    AV_CODEC_ID_TARGA,\n    AV_CODEC_ID_DSICINVIDEO,\n    AV_CODEC_ID_TIERTEXSEQVIDEO,\n    AV_CODEC_ID_TIFF,\n    AV_CODEC_ID_GIF,\n    AV_CODEC_ID_DXA,\n    AV_CODEC_ID_DNXHD,\n    AV_CODEC_ID_THP,\n    AV_CODEC_ID_SGI,\n    AV_CODEC_ID_C93,\n    AV_CODEC_ID_BETHSOFTVID,\n    AV_CODEC_ID_PTX,\n    AV_CODEC_ID_TXD,\n    AV_CODEC_ID_VP6A,\n    AV_CODEC_ID_AMV,\n    AV_CODEC_ID_VB,\n    AV_CODEC_ID_PCX,\n    AV_CODEC_ID_SUNRAST,\n    AV_CODEC_ID_INDEO4,\n    AV_CODEC_ID_INDEO5,\n    AV_CODEC_ID_MIMIC,\n    AV_CODEC_ID_RL2,\n    AV_CODEC_ID_ESCAPE124,\n    AV_CODEC_ID_DIRAC,\n    AV_CODEC_ID_BFI,\n    AV_CODEC_ID_CMV,\n    AV_CODEC_ID_MOTIONPIXELS,\n    AV_CODEC_ID_TGV,\n    AV_CODEC_ID_TGQ,\n    AV_CODEC_ID_TQI,\n    AV_CODEC_ID_AURA,\n    AV_CODEC_ID_AURA2,\n    AV_CODEC_ID_V210X,\n    AV_CODEC_ID_TMV,\n    AV_CODEC_ID_V210,\n    AV_CODEC_ID_DPX,\n    AV_CODEC_ID_MAD,\n    AV_CODEC_ID_FRWU,\n    AV_CODEC_ID_FLASHSV2,\n    AV_CODEC_ID_CDGRAPHICS,\n    AV_CODEC_ID_R210,\n    AV_CODEC_ID_ANM,\n    AV_CODEC_ID_BINKVIDEO,\n    AV_CODEC_ID_IFF_ILBM,\n#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM\n    AV_CODEC_ID_KGV1,\n    AV_CODEC_ID_YOP,\n    AV_CODEC_ID_VP8,\n    AV_CODEC_ID_PICTOR,\n    AV_CODEC_ID_ANSI,\n    AV_CODEC_ID_A64_MULTI,\n    AV_CODEC_ID_A64_MULTI5,\n    AV_CODEC_ID_R10K,\n    AV_CODEC_ID_MXPEG,\n    AV_CODEC_ID_LAGARITH,\n    AV_CODEC_ID_PRORES,\n    AV_CODEC_ID_JV,\n    AV_CODEC_ID_DFA,\n    AV_CODEC_ID_WMV3IMAGE,\n    AV_CODEC_ID_VC1IMAGE,\n    AV_CODEC_ID_UTVIDEO,\n    AV_CODEC_ID_BMV_VIDEO,\n    AV_CODEC_ID_VBLE,\n    AV_CODEC_ID_DXTORY,\n    AV_CODEC_ID_V410,\n    AV_CODEC_ID_XWD,\n    AV_CODEC_ID_CDXL,\n    AV_CODEC_ID_XBM,\n    AV_CODEC_ID_ZEROCODEC,\n    AV_CODEC_ID_MSS1,\n    AV_CODEC_ID_MSA1,\n    AV_CODEC_ID_TSCC2,\n    AV_CODEC_ID_MTS2,\n    AV_CODEC_ID_CLLC,\n    AV_CODEC_ID_MSS2,\n    AV_CODEC_ID_VP9,\n    AV_CODEC_ID_AIC,\n    AV_CODEC_ID_ESCAPE130,\n    AV_CODEC_ID_G2M,\n    AV_CODEC_ID_WEBP,\n    AV_CODEC_ID_HNM4_VIDEO,\n    AV_CODEC_ID_HEVC,\n#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC\n    AV_CODEC_ID_FIC,\n    AV_CODEC_ID_ALIAS_PIX,\n    AV_CODEC_ID_BRENDER_PIX,\n    AV_CODEC_ID_PAF_VIDEO,\n    AV_CODEC_ID_EXR,\n    AV_CODEC_ID_VP7,\n    AV_CODEC_ID_SANM,\n    AV_CODEC_ID_SGIRLE,\n    AV_CODEC_ID_MVC1,\n    AV_CODEC_ID_MVC2,\n    AV_CODEC_ID_HQX,\n    AV_CODEC_ID_TDSC,\n    AV_CODEC_ID_HQ_HQA,\n    AV_CODEC_ID_HAP,\n    AV_CODEC_ID_DDS,\n    AV_CODEC_ID_DXV,\n    AV_CODEC_ID_SCREENPRESSO,\n    AV_CODEC_ID_RSCC,\n    AV_CODEC_ID_AVS2,\n    AV_CODEC_ID_PGX,\n    AV_CODEC_ID_AVS3,\n    AV_CODEC_ID_MSP2,\n    AV_CODEC_ID_VVC,\n#define AV_CODEC_ID_H266 AV_CODEC_ID_VVC\n    AV_CODEC_ID_Y41P,\n    AV_CODEC_ID_AVRP,\n    AV_CODEC_ID_012V,\n    AV_CODEC_ID_AVUI,\n    AV_CODEC_ID_AYUV,\n    AV_CODEC_ID_TARGA_Y216,\n    AV_CODEC_ID_V308,\n    AV_CODEC_ID_V408,\n    AV_CODEC_ID_YUV4,\n    AV_CODEC_ID_AVRN,\n    AV_CODEC_ID_CPIA,\n    AV_CODEC_ID_XFACE,\n    AV_CODEC_ID_SNOW,\n    AV_CODEC_ID_SMVJPEG,\n    AV_CODEC_ID_APNG,\n    AV_CODEC_ID_DAALA,\n    AV_CODEC_ID_CFHD,\n    AV_CODEC_ID_TRUEMOTION2RT,\n    AV_CODEC_ID_M101,\n    AV_CODEC_ID_MAGICYUV,\n    AV_CODEC_ID_SHEERVIDEO,\n    AV_CODEC_ID_YLC,\n    AV_CODEC_ID_PSD,\n    AV_CODEC_ID_PIXLET,\n    AV_CODEC_ID_SPEEDHQ,\n    AV_CODEC_ID_FMVC,\n    AV_CODEC_ID_SCPR,\n    AV_CODEC_ID_CLEARVIDEO,\n    AV_CODEC_ID_XPM,\n    AV_CODEC_ID_AV1,\n    AV_CODEC_ID_BITPACKED,\n    AV_CODEC_ID_MSCC,\n    AV_CODEC_ID_SRGC,\n    AV_CODEC_ID_SVG,\n    AV_CODEC_ID_GDV,\n    AV_CODEC_ID_FITS,\n    AV_CODEC_ID_IMM4,\n    AV_CODEC_ID_PROSUMER,\n    AV_CODEC_ID_MWSC,\n    AV_CODEC_ID_WCMV,\n    AV_CODEC_ID_RASC,\n    AV_CODEC_ID_HYMT,\n    AV_CODEC_ID_ARBC,\n    AV_CODEC_ID_AGM,\n    AV_CODEC_ID_LSCR,\n    AV_CODEC_ID_VP4,\n    AV_CODEC_ID_IMM5,\n    AV_CODEC_ID_MVDV,\n    AV_CODEC_ID_MVHA,\n    AV_CODEC_ID_CDTOONS,\n    AV_CODEC_ID_MV30,\n    AV_CODEC_ID_NOTCHLC,\n    AV_CODEC_ID_PFM,\n    AV_CODEC_ID_MOBICLIP,\n    AV_CODEC_ID_PHOTOCD,\n    AV_CODEC_ID_IPU,\n    AV_CODEC_ID_ARGO,\n    AV_CODEC_ID_CRI,\n    AV_CODEC_ID_SIMBIOSIS_IMX,\n    AV_CODEC_ID_SGA_VIDEO,\n    AV_CODEC_ID_GEM,\n    AV_CODEC_ID_VBN,\n    AV_CODEC_ID_JPEGXL,\n    AV_CODEC_ID_QOI,\n    AV_CODEC_ID_PHM,\n\n    /* various PCM \"codecs\" */\n    AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs\n    AV_CODEC_ID_PCM_S16LE = 0x10000,\n    AV_CODEC_ID_PCM_S16BE,\n    AV_CODEC_ID_PCM_U16LE,\n    AV_CODEC_ID_PCM_U16BE,\n    AV_CODEC_ID_PCM_S8,\n    AV_CODEC_ID_PCM_U8,\n    AV_CODEC_ID_PCM_MULAW,\n    AV_CODEC_ID_PCM_ALAW,\n    AV_CODEC_ID_PCM_S32LE,\n    AV_CODEC_ID_PCM_S32BE,\n    AV_CODEC_ID_PCM_U32LE,\n    AV_CODEC_ID_PCM_U32BE,\n    AV_CODEC_ID_PCM_S24LE,\n    AV_CODEC_ID_PCM_S24BE,\n    AV_CODEC_ID_PCM_U24LE,\n    AV_CODEC_ID_PCM_U24BE,\n    AV_CODEC_ID_PCM_S24DAUD,\n    AV_CODEC_ID_PCM_ZORK,\n    AV_CODEC_ID_PCM_S16LE_PLANAR,\n    AV_CODEC_ID_PCM_DVD,\n    AV_CODEC_ID_PCM_F32BE,\n    AV_CODEC_ID_PCM_F32LE,\n    AV_CODEC_ID_PCM_F64BE,\n    AV_CODEC_ID_PCM_F64LE,\n    AV_CODEC_ID_PCM_BLURAY,\n    AV_CODEC_ID_PCM_LXF,\n    AV_CODEC_ID_S302M,\n    AV_CODEC_ID_PCM_S8_PLANAR,\n    AV_CODEC_ID_PCM_S24LE_PLANAR,\n    AV_CODEC_ID_PCM_S32LE_PLANAR,\n    AV_CODEC_ID_PCM_S16BE_PLANAR,\n    AV_CODEC_ID_PCM_S64LE,\n    AV_CODEC_ID_PCM_S64BE,\n    AV_CODEC_ID_PCM_F16LE,\n    AV_CODEC_ID_PCM_F24LE,\n    AV_CODEC_ID_PCM_VIDC,\n    AV_CODEC_ID_PCM_SGA,\n\n    /* various ADPCM codecs */\n    AV_CODEC_ID_ADPCM_IMA_QT = 0x11000,\n    AV_CODEC_ID_ADPCM_IMA_WAV,\n    AV_CODEC_ID_ADPCM_IMA_DK3,\n    AV_CODEC_ID_ADPCM_IMA_DK4,\n    AV_CODEC_ID_ADPCM_IMA_WS,\n    AV_CODEC_ID_ADPCM_IMA_SMJPEG,\n    AV_CODEC_ID_ADPCM_MS,\n    AV_CODEC_ID_ADPCM_4XM,\n    AV_CODEC_ID_ADPCM_XA,\n    AV_CODEC_ID_ADPCM_ADX,\n    AV_CODEC_ID_ADPCM_EA,\n    AV_CODEC_ID_ADPCM_G726,\n    AV_CODEC_ID_ADPCM_CT,\n    AV_CODEC_ID_ADPCM_SWF,\n    AV_CODEC_ID_ADPCM_YAMAHA,\n    AV_CODEC_ID_ADPCM_SBPRO_4,\n    AV_CODEC_ID_ADPCM_SBPRO_3,\n    AV_CODEC_ID_ADPCM_SBPRO_2,\n    AV_CODEC_ID_ADPCM_THP,\n    AV_CODEC_ID_ADPCM_IMA_AMV,\n    AV_CODEC_ID_ADPCM_EA_R1,\n    AV_CODEC_ID_ADPCM_EA_R3,\n    AV_CODEC_ID_ADPCM_EA_R2,\n    AV_CODEC_ID_ADPCM_IMA_EA_SEAD,\n    AV_CODEC_ID_ADPCM_IMA_EA_EACS,\n    AV_CODEC_ID_ADPCM_EA_XAS,\n    AV_CODEC_ID_ADPCM_EA_MAXIS_XA,\n    AV_CODEC_ID_ADPCM_IMA_ISS,\n    AV_CODEC_ID_ADPCM_G722,\n    AV_CODEC_ID_ADPCM_IMA_APC,\n    AV_CODEC_ID_ADPCM_VIMA,\n    AV_CODEC_ID_ADPCM_AFC,\n    AV_CODEC_ID_ADPCM_IMA_OKI,\n    AV_CODEC_ID_ADPCM_DTK,\n    AV_CODEC_ID_ADPCM_IMA_RAD,\n    AV_CODEC_ID_ADPCM_G726LE,\n    AV_CODEC_ID_ADPCM_THP_LE,\n    AV_CODEC_ID_ADPCM_PSX,\n    AV_CODEC_ID_ADPCM_AICA,\n    AV_CODEC_ID_ADPCM_IMA_DAT4,\n    AV_CODEC_ID_ADPCM_MTAF,\n    AV_CODEC_ID_ADPCM_AGM,\n    AV_CODEC_ID_ADPCM_ARGO,\n    AV_CODEC_ID_ADPCM_IMA_SSI,\n    AV_CODEC_ID_ADPCM_ZORK,\n    AV_CODEC_ID_ADPCM_IMA_APM,\n    AV_CODEC_ID_ADPCM_IMA_ALP,\n    AV_CODEC_ID_ADPCM_IMA_MTF,\n    AV_CODEC_ID_ADPCM_IMA_CUNNING,\n    AV_CODEC_ID_ADPCM_IMA_MOFLEX,\n    AV_CODEC_ID_ADPCM_IMA_ACORN,\n\n    /* AMR */\n    AV_CODEC_ID_AMR_NB = 0x12000,\n    AV_CODEC_ID_AMR_WB,\n\n    /* RealAudio codecs*/\n    AV_CODEC_ID_RA_144 = 0x13000,\n    AV_CODEC_ID_RA_288,\n\n    /* various DPCM codecs */\n    AV_CODEC_ID_ROQ_DPCM = 0x14000,\n    AV_CODEC_ID_INTERPLAY_DPCM,\n    AV_CODEC_ID_XAN_DPCM,\n    AV_CODEC_ID_SOL_DPCM,\n    AV_CODEC_ID_SDX2_DPCM,\n    AV_CODEC_ID_GREMLIN_DPCM,\n    AV_CODEC_ID_DERF_DPCM,\n\n    /* audio codecs */\n    AV_CODEC_ID_MP2 = 0x15000,\n    AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3\n    AV_CODEC_ID_AAC,\n    AV_CODEC_ID_AC3,\n    AV_CODEC_ID_DTS,\n    AV_CODEC_ID_VORBIS,\n    AV_CODEC_ID_DVAUDIO,\n    AV_CODEC_ID_WMAV1,\n    AV_CODEC_ID_WMAV2,\n    AV_CODEC_ID_MACE3,\n    AV_CODEC_ID_MACE6,\n    AV_CODEC_ID_VMDAUDIO,\n    AV_CODEC_ID_FLAC,\n    AV_CODEC_ID_MP3ADU,\n    AV_CODEC_ID_MP3ON4,\n    AV_CODEC_ID_SHORTEN,\n    AV_CODEC_ID_ALAC,\n    AV_CODEC_ID_WESTWOOD_SND1,\n    AV_CODEC_ID_GSM, ///< as in Berlin toast format\n    AV_CODEC_ID_QDM2,\n    AV_CODEC_ID_COOK,\n    AV_CODEC_ID_TRUESPEECH,\n    AV_CODEC_ID_TTA,\n    AV_CODEC_ID_SMACKAUDIO,\n    AV_CODEC_ID_QCELP,\n    AV_CODEC_ID_WAVPACK,\n    AV_CODEC_ID_DSICINAUDIO,\n    AV_CODEC_ID_IMC,\n    AV_CODEC_ID_MUSEPACK7,\n    AV_CODEC_ID_MLP,\n    AV_CODEC_ID_GSM_MS, /* as found in WAV */\n    AV_CODEC_ID_ATRAC3,\n    AV_CODEC_ID_APE,\n    AV_CODEC_ID_NELLYMOSER,\n    AV_CODEC_ID_MUSEPACK8,\n    AV_CODEC_ID_SPEEX,\n    AV_CODEC_ID_WMAVOICE,\n    AV_CODEC_ID_WMAPRO,\n    AV_CODEC_ID_WMALOSSLESS,\n    AV_CODEC_ID_ATRAC3P,\n    AV_CODEC_ID_EAC3,\n    AV_CODEC_ID_SIPR,\n    AV_CODEC_ID_MP1,\n    AV_CODEC_ID_TWINVQ,\n    AV_CODEC_ID_TRUEHD,\n    AV_CODEC_ID_MP4ALS,\n    AV_CODEC_ID_ATRAC1,\n    AV_CODEC_ID_BINKAUDIO_RDFT,\n    AV_CODEC_ID_BINKAUDIO_DCT,\n    AV_CODEC_ID_AAC_LATM,\n    AV_CODEC_ID_QDMC,\n    AV_CODEC_ID_CELT,\n    AV_CODEC_ID_G723_1,\n    AV_CODEC_ID_G729,\n    AV_CODEC_ID_8SVX_EXP,\n    AV_CODEC_ID_8SVX_FIB,\n    AV_CODEC_ID_BMV_AUDIO,\n    AV_CODEC_ID_RALF,\n    AV_CODEC_ID_IAC,\n    AV_CODEC_ID_ILBC,\n    AV_CODEC_ID_OPUS,\n    AV_CODEC_ID_COMFORT_NOISE,\n    AV_CODEC_ID_TAK,\n    AV_CODEC_ID_METASOUND,\n    AV_CODEC_ID_PAF_AUDIO,\n    AV_CODEC_ID_ON2AVC,\n    AV_CODEC_ID_DSS_SP,\n    AV_CODEC_ID_CODEC2,\n    AV_CODEC_ID_FFWAVESYNTH,\n    AV_CODEC_ID_SONIC,\n    AV_CODEC_ID_SONIC_LS,\n    AV_CODEC_ID_EVRC,\n    AV_CODEC_ID_SMV,\n    AV_CODEC_ID_DSD_LSBF,\n    AV_CODEC_ID_DSD_MSBF,\n    AV_CODEC_ID_DSD_LSBF_PLANAR,\n    AV_CODEC_ID_DSD_MSBF_PLANAR,\n    AV_CODEC_ID_4GV,\n    AV_CODEC_ID_INTERPLAY_ACM,\n    AV_CODEC_ID_XMA1,\n    AV_CODEC_ID_XMA2,\n    AV_CODEC_ID_DST,\n    AV_CODEC_ID_ATRAC3AL,\n    AV_CODEC_ID_ATRAC3PAL,\n    AV_CODEC_ID_DOLBY_E,\n    AV_CODEC_ID_APTX,\n    AV_CODEC_ID_APTX_HD,\n    AV_CODEC_ID_SBC,\n    AV_CODEC_ID_ATRAC9,\n    AV_CODEC_ID_HCOM,\n    AV_CODEC_ID_ACELP_KELVIN,\n    AV_CODEC_ID_MPEGH_3D_AUDIO,\n    AV_CODEC_ID_SIREN,\n    AV_CODEC_ID_HCA,\n    AV_CODEC_ID_FASTAUDIO,\n    AV_CODEC_ID_MSNSIREN,\n    AV_CODEC_ID_DFPWM,\n\n    /* subtitle codecs */\n    AV_CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at the start of subtitle codecs.\n    AV_CODEC_ID_DVD_SUBTITLE = 0x17000,\n    AV_CODEC_ID_DVB_SUBTITLE,\n    AV_CODEC_ID_TEXT,  ///< raw UTF-8 text\n    AV_CODEC_ID_XSUB,\n    AV_CODEC_ID_SSA,\n    AV_CODEC_ID_MOV_TEXT,\n    AV_CODEC_ID_HDMV_PGS_SUBTITLE,\n    AV_CODEC_ID_DVB_TELETEXT,\n    AV_CODEC_ID_SRT,\n    AV_CODEC_ID_MICRODVD,\n    AV_CODEC_ID_EIA_608,\n    AV_CODEC_ID_JACOSUB,\n    AV_CODEC_ID_SAMI,\n    AV_CODEC_ID_REALTEXT,\n    AV_CODEC_ID_STL,\n    AV_CODEC_ID_SUBVIEWER1,\n    AV_CODEC_ID_SUBVIEWER,\n    AV_CODEC_ID_SUBRIP,\n    AV_CODEC_ID_WEBVTT,\n    AV_CODEC_ID_MPL2,\n    AV_CODEC_ID_VPLAYER,\n    AV_CODEC_ID_PJS,\n    AV_CODEC_ID_ASS,\n    AV_CODEC_ID_HDMV_TEXT_SUBTITLE,\n    AV_CODEC_ID_TTML,\n    AV_CODEC_ID_ARIB_CAPTION,\n\n    /* other specific kind of codecs (generally used for attachments) */\n    AV_CODEC_ID_FIRST_UNKNOWN = 0x18000,           ///< A dummy ID pointing at the start of various fake codecs.\n    AV_CODEC_ID_TTF = 0x18000,\n\n    AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream.\n    AV_CODEC_ID_EPG,\n    AV_CODEC_ID_BINTEXT,\n    AV_CODEC_ID_XBIN,\n    AV_CODEC_ID_IDF,\n    AV_CODEC_ID_OTF,\n    AV_CODEC_ID_SMPTE_KLV,\n    AV_CODEC_ID_DVD_NAV,\n    AV_CODEC_ID_TIMED_ID3,\n    AV_CODEC_ID_BIN_DATA,\n\n\n    AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it\n\n    AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS\n                                * stream (only used by libavformat) */\n    AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems\n                                * stream (only used by libavformat) */\n    AV_CODEC_ID_FFMETADATA = 0x21000,   ///< Dummy codec for streams containing only metadata information.\n    AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket\n};\n\n/**\n * Get the type of the given codec.\n */\nenum AVMediaType avcodec_get_type(enum AVCodecID codec_id);\n\n/**\n * Get the name of a codec.\n * @return  a static string identifying the codec; never NULL\n */\nconst char *avcodec_get_name(enum AVCodecID id);\n\n/**\n * Return codec bits per sample.\n *\n * @param[in] codec_id the codec\n * @return Number of bits per sample or zero if unknown for the given codec.\n */\nint av_get_bits_per_sample(enum AVCodecID codec_id);\n\n/**\n * Return codec bits per sample.\n * Only return non-zero if the bits per sample is exactly correct, not an\n * approximation.\n *\n * @param[in] codec_id the codec\n * @return Number of bits per sample or zero if unknown for the given codec.\n */\nint av_get_exact_bits_per_sample(enum AVCodecID codec_id);\n\n/**\n * Return a name for the specified profile, if available.\n *\n * @param codec_id the ID of the codec to which the requested profile belongs\n * @param profile the profile value for which a name is requested\n * @return A name for the profile if found, NULL otherwise.\n *\n * @note unlike av_get_profile_name(), which searches a list of profiles\n *       supported by a specific decoder or encoder implementation, this\n *       function searches the list of profiles from the AVCodecDescriptor\n */\nconst char *avcodec_profile_name(enum AVCodecID codec_id, int profile);\n\n/**\n * Return the PCM codec associated with a sample format.\n * @param be  endianness, 0 for little, 1 for big,\n *            -1 (or anything else) for native\n * @return  AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE\n */\nenum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be);\n\n/**\n * @}\n */\n\n#endif // AVCODEC_CODEC_ID_H\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/codec_par.h",
    "content": "/*\n * Codec parameters public API\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_CODEC_PAR_H\n#define AVCODEC_CODEC_PAR_H\n\n#include <stdint.h>\n\n#include \"libavutil/avutil.h\"\n#include \"libavutil/channel_layout.h\"\n#include \"libavutil/rational.h\"\n#include \"libavutil/pixfmt.h\"\n\n#include \"codec_id.h\"\n\n/**\n * @addtogroup lavc_core\n */\n\nenum AVFieldOrder {\n    AV_FIELD_UNKNOWN,\n    AV_FIELD_PROGRESSIVE,\n    AV_FIELD_TT,          //< Top coded_first, top displayed first\n    AV_FIELD_BB,          //< Bottom coded first, bottom displayed first\n    AV_FIELD_TB,          //< Top coded first, bottom displayed first\n    AV_FIELD_BT,          //< Bottom coded first, top displayed first\n};\n\n/**\n * This struct describes the properties of an encoded stream.\n *\n * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must\n * be allocated with avcodec_parameters_alloc() and freed with\n * avcodec_parameters_free().\n */\ntypedef struct AVCodecParameters {\n    /**\n     * General type of the encoded data.\n     */\n    enum AVMediaType codec_type;\n    /**\n     * Specific type of the encoded data (the codec used).\n     */\n    enum AVCodecID   codec_id;\n    /**\n     * Additional information about the codec (corresponds to the AVI FOURCC).\n     */\n    uint32_t         codec_tag;\n\n    /**\n     * Extra binary data needed for initializing the decoder, codec-dependent.\n     *\n     * Must be allocated with av_malloc() and will be freed by\n     * avcodec_parameters_free(). The allocated size of extradata must be at\n     * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding\n     * bytes zeroed.\n     */\n    uint8_t *extradata;\n    /**\n     * Size of the extradata content in bytes.\n     */\n    int      extradata_size;\n\n    /**\n     * - video: the pixel format, the value corresponds to enum AVPixelFormat.\n     * - audio: the sample format, the value corresponds to enum AVSampleFormat.\n     */\n    int format;\n\n    /**\n     * The average bitrate of the encoded data (in bits per second).\n     */\n    int64_t bit_rate;\n\n    /**\n     * The number of bits per sample in the codedwords.\n     *\n     * This is basically the bitrate per sample. It is mandatory for a bunch of\n     * formats to actually decode them. It's the number of bits for one sample in\n     * the actual coded bitstream.\n     *\n     * This could be for example 4 for ADPCM\n     * For PCM formats this matches bits_per_raw_sample\n     * Can be 0\n     */\n    int bits_per_coded_sample;\n\n    /**\n     * This is the number of valid bits in each output sample. If the\n     * sample format has more bits, the least significant bits are additional\n     * padding bits, which are always 0. Use right shifts to reduce the sample\n     * to its actual size. For example, audio formats with 24 bit samples will\n     * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32.\n     * To get the original sample use \"(int32_t)sample >> 8\".\"\n     *\n     * For ADPCM this might be 12 or 16 or similar\n     * Can be 0\n     */\n    int bits_per_raw_sample;\n\n    /**\n     * Codec-specific bitstream restrictions that the stream conforms to.\n     */\n    int profile;\n    int level;\n\n    /**\n     * Video only. The dimensions of the video frame in pixels.\n     */\n    int width;\n    int height;\n\n    /**\n     * Video only. The aspect ratio (width / height) which a single pixel\n     * should have when displayed.\n     *\n     * When the aspect ratio is unknown / undefined, the numerator should be\n     * set to 0 (the denominator may have any value).\n     */\n    AVRational sample_aspect_ratio;\n\n    /**\n     * Video only. The order of the fields in interlaced video.\n     */\n    enum AVFieldOrder                  field_order;\n\n    /**\n     * Video only. Additional colorspace characteristics.\n     */\n    enum AVColorRange                  color_range;\n    enum AVColorPrimaries              color_primaries;\n    enum AVColorTransferCharacteristic color_trc;\n    enum AVColorSpace                  color_space;\n    enum AVChromaLocation              chroma_location;\n\n    /**\n     * Video only. Number of delayed frames.\n     */\n    int video_delay;\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * Audio only. The channel layout bitmask. May be 0 if the channel layout is\n     * unknown or unspecified, otherwise the number of bits set must be equal to\n     * the channels field.\n     * @deprecated use ch_layout\n     */\n    attribute_deprecated\n    uint64_t channel_layout;\n    /**\n     * Audio only. The number of audio channels.\n     * @deprecated use ch_layout.nb_channels\n     */\n    attribute_deprecated\n    int      channels;\n#endif\n    /**\n     * Audio only. The number of audio samples per second.\n     */\n    int      sample_rate;\n    /**\n     * Audio only. The number of bytes per coded audio frame, required by some\n     * formats.\n     *\n     * Corresponds to nBlockAlign in WAVEFORMATEX.\n     */\n    int      block_align;\n    /**\n     * Audio only. Audio frame size, if known. Required by some formats to be static.\n     */\n    int      frame_size;\n\n    /**\n     * Audio only. The amount of padding (in samples) inserted by the encoder at\n     * the beginning of the audio. I.e. this number of leading decoded samples\n     * must be discarded by the caller to get the original audio without leading\n     * padding.\n     */\n    int initial_padding;\n    /**\n     * Audio only. The amount of padding (in samples) appended by the encoder to\n     * the end of the audio. I.e. this number of decoded samples must be\n     * discarded by the caller from the end of the stream to get the original\n     * audio without any trailing padding.\n     */\n    int trailing_padding;\n    /**\n     * Audio only. Number of samples to skip after a discontinuity.\n     */\n    int seek_preroll;\n\n    /**\n     * Audio only. The channel layout and number of channels.\n     */\n    AVChannelLayout ch_layout;\n} AVCodecParameters;\n\n/**\n * Allocate a new AVCodecParameters and set its fields to default values\n * (unknown/invalid/0). The returned struct must be freed with\n * avcodec_parameters_free().\n */\nAVCodecParameters *avcodec_parameters_alloc(void);\n\n/**\n * Free an AVCodecParameters instance and everything associated with it and\n * write NULL to the supplied pointer.\n */\nvoid avcodec_parameters_free(AVCodecParameters **par);\n\n/**\n * Copy the contents of src to dst. Any allocated fields in dst are freed and\n * replaced with newly allocated duplicates of the corresponding fields in src.\n *\n * @return >= 0 on success, a negative AVERROR code on failure.\n */\nint avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src);\n\n/**\n * This function is the same as av_get_audio_frame_duration(), except it works\n * with AVCodecParameters instead of an AVCodecContext.\n */\nint av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes);\n\n/**\n * @}\n */\n\n#endif // AVCODEC_CODEC_PAR_H\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/d3d11va.h",
    "content": "/*\n * Direct3D11 HW acceleration\n *\n * copyright (c) 2009 Laurent Aimar\n * copyright (c) 2015 Steve Lhomme\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_D3D11VA_H\n#define AVCODEC_D3D11VA_H\n\n/**\n * @file\n * @ingroup lavc_codec_hwaccel_d3d11va\n * Public libavcodec D3D11VA header.\n */\n\n#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602\n#undef _WIN32_WINNT\n#define _WIN32_WINNT 0x0602\n#endif\n\n#include <stdint.h>\n#include <d3d11.h>\n\n/**\n * @defgroup lavc_codec_hwaccel_d3d11va Direct3D11\n * @ingroup lavc_codec_hwaccel\n *\n * @{\n */\n\n#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for Direct3D11 and old UVD/UVD+ ATI video cards\n#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO    2 ///< Work around for Direct3D11 and old Intel GPUs with ClearVideo interface\n\n/**\n * This structure is used to provides the necessary configurations and data\n * to the Direct3D11 FFmpeg HWAccel implementation.\n *\n * The application must make it available as AVCodecContext.hwaccel_context.\n *\n * Use av_d3d11va_alloc_context() exclusively to allocate an AVD3D11VAContext.\n */\ntypedef struct AVD3D11VAContext {\n    /**\n     * D3D11 decoder object\n     */\n    ID3D11VideoDecoder *decoder;\n\n    /**\n      * D3D11 VideoContext\n      */\n    ID3D11VideoContext *video_context;\n\n    /**\n     * D3D11 configuration used to create the decoder\n     */\n    D3D11_VIDEO_DECODER_CONFIG *cfg;\n\n    /**\n     * The number of surface in the surface array\n     */\n    unsigned surface_count;\n\n    /**\n     * The array of Direct3D surfaces used to create the decoder\n     */\n    ID3D11VideoDecoderOutputView **surface;\n\n    /**\n     * A bit field configuring the workarounds needed for using the decoder\n     */\n    uint64_t workaround;\n\n    /**\n     * Private to the FFmpeg AVHWAccel implementation\n     */\n    unsigned report_id;\n\n    /**\n      * Mutex to access video_context\n      */\n    HANDLE  context_mutex;\n} AVD3D11VAContext;\n\n/**\n * Allocate an AVD3D11VAContext.\n *\n * @return Newly-allocated AVD3D11VAContext or NULL on failure.\n */\nAVD3D11VAContext *av_d3d11va_alloc_context(void);\n\n/**\n * @}\n */\n\n#endif /* AVCODEC_D3D11VA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/defs.h",
    "content": "/*\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_DEFS_H\n#define AVCODEC_DEFS_H\n\n/**\n * @file\n * @ingroup libavc\n * Misc types and constants that do not belong anywhere else.\n */\n\n#include <stdint.h>\n#include <stdlib.h>\n\n/**\n * @ingroup lavc_decoding\n * Required number of additionally allocated bytes at the end of the input bitstream for decoding.\n * This is mainly needed because some optimized bitstream readers read\n * 32 or 64 bit at once and could read over the end.<br>\n * Note: If the first 23 bits of the additional bytes are not 0, then damaged\n * MPEG bitstreams could cause overread and segfault.\n */\n#define AV_INPUT_BUFFER_PADDING_SIZE 64\n\n/**\n * @ingroup lavc_decoding\n */\nenum AVDiscard{\n    /* We leave some space between them for extensions (drop some\n     * keyframes for intra-only or drop just some bidir frames). */\n    AVDISCARD_NONE    =-16, ///< discard nothing\n    AVDISCARD_DEFAULT =  0, ///< discard useless packets like 0 size packets in avi\n    AVDISCARD_NONREF  =  8, ///< discard all non reference\n    AVDISCARD_BIDIR   = 16, ///< discard all bidirectional frames\n    AVDISCARD_NONINTRA= 24, ///< discard all non intra frames\n    AVDISCARD_NONKEY  = 32, ///< discard all frames except keyframes\n    AVDISCARD_ALL     = 48, ///< discard all\n};\n\nenum AVAudioServiceType {\n    AV_AUDIO_SERVICE_TYPE_MAIN              = 0,\n    AV_AUDIO_SERVICE_TYPE_EFFECTS           = 1,\n    AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2,\n    AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED  = 3,\n    AV_AUDIO_SERVICE_TYPE_DIALOGUE          = 4,\n    AV_AUDIO_SERVICE_TYPE_COMMENTARY        = 5,\n    AV_AUDIO_SERVICE_TYPE_EMERGENCY         = 6,\n    AV_AUDIO_SERVICE_TYPE_VOICE_OVER        = 7,\n    AV_AUDIO_SERVICE_TYPE_KARAOKE           = 8,\n    AV_AUDIO_SERVICE_TYPE_NB                   , ///< Not part of ABI\n};\n\n/**\n * Pan Scan area.\n * This specifies the area which should be displayed.\n * Note there may be multiple such areas for one frame.\n */\ntypedef struct AVPanScan {\n    /**\n     * id\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n    int id;\n\n    /**\n     * width and height in 1/16 pel\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n    int width;\n    int height;\n\n    /**\n     * position of the top left corner in 1/16 pel for up to 3 fields/frames\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n    int16_t position[3][2];\n} AVPanScan;\n\n/**\n * This structure describes the bitrate properties of an encoded bitstream. It\n * roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD\n * parameters for H.264/HEVC.\n */\ntypedef struct AVCPBProperties {\n    /**\n     * Maximum bitrate of the stream, in bits per second.\n     * Zero if unknown or unspecified.\n     */\n    int64_t max_bitrate;\n    /**\n     * Minimum bitrate of the stream, in bits per second.\n     * Zero if unknown or unspecified.\n     */\n    int64_t min_bitrate;\n    /**\n     * Average bitrate of the stream, in bits per second.\n     * Zero if unknown or unspecified.\n     */\n    int64_t avg_bitrate;\n\n    /**\n     * The size of the buffer to which the ratecontrol is applied, in bits.\n     * Zero if unknown or unspecified.\n     */\n    int64_t buffer_size;\n\n    /**\n     * The delay between the time the packet this structure is associated with\n     * is received and the time when it should be decoded, in periods of a 27MHz\n     * clock.\n     *\n     * UINT64_MAX when unknown or unspecified.\n     */\n    uint64_t vbv_delay;\n} AVCPBProperties;\n\n/**\n * Allocate a CPB properties structure and initialize its fields to default\n * values.\n *\n * @param size if non-NULL, the size of the allocated struct will be written\n *             here. This is useful for embedding it in side data.\n *\n * @return the newly allocated struct or NULL on failure\n */\nAVCPBProperties *av_cpb_properties_alloc(size_t *size);\n\n/**\n * This structure supplies correlation between a packet timestamp and a wall clock\n * production time. The definition follows the Producer Reference Time ('prft')\n * as defined in ISO/IEC 14496-12\n */\ntypedef struct AVProducerReferenceTime {\n    /**\n     * A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()).\n     */\n    int64_t wallclock;\n    int flags;\n} AVProducerReferenceTime;\n\n/**\n * Encode extradata length to a buffer. Used by xiph codecs.\n *\n * @param s buffer to write to; must be at least (v/255+1) bytes long\n * @param v size of extradata in bytes\n * @return number of bytes written to the buffer.\n */\nunsigned int av_xiphlacing(unsigned char *s, unsigned int v);\n\n#endif // AVCODEC_DEFS_H\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/dirac.h",
    "content": "/*\n * Copyright (C) 2007 Marco Gerards <marco@gnu.org>\n * Copyright (C) 2009 David Conrad\n * Copyright (C) 2011 Jordi Ortiz\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_DIRAC_H\n#define AVCODEC_DIRAC_H\n\n/**\n * @file\n * Interface to Dirac Decoder/Encoder\n * @author Marco Gerards <marco@gnu.org>\n * @author David Conrad\n * @author Jordi Ortiz\n */\n\n#include \"avcodec.h\"\n\n/**\n * The spec limits the number of wavelet decompositions to 4 for both\n * level 1 (VC-2) and 128 (long-gop default).\n * 5 decompositions is the maximum before >16-bit buffers are needed.\n * Schroedinger allows this for DD 9,7 and 13,7 wavelets only, limiting\n * the others to 4 decompositions (or 3 for the fidelity filter).\n *\n * We use this instead of MAX_DECOMPOSITIONS to save some memory.\n */\n#define MAX_DWT_LEVELS 5\n\n/**\n * Parse code values:\n *\n * Dirac Specification ->\n * 9.6.1  Table 9.1\n *\n * VC-2 Specification  ->\n * 10.4.1 Table 10.1\n */\n\nenum DiracParseCodes {\n    DIRAC_PCODE_SEQ_HEADER      = 0x00,\n    DIRAC_PCODE_END_SEQ         = 0x10,\n    DIRAC_PCODE_AUX             = 0x20,\n    DIRAC_PCODE_PAD             = 0x30,\n    DIRAC_PCODE_PICTURE_CODED   = 0x08,\n    DIRAC_PCODE_PICTURE_RAW     = 0x48,\n    DIRAC_PCODE_PICTURE_LOW_DEL = 0xC8,\n    DIRAC_PCODE_PICTURE_HQ      = 0xE8,\n    DIRAC_PCODE_INTER_NOREF_CO1 = 0x0A,\n    DIRAC_PCODE_INTER_NOREF_CO2 = 0x09,\n    DIRAC_PCODE_INTER_REF_CO1   = 0x0D,\n    DIRAC_PCODE_INTER_REF_CO2   = 0x0E,\n    DIRAC_PCODE_INTRA_REF_CO    = 0x0C,\n    DIRAC_PCODE_INTRA_REF_RAW   = 0x4C,\n    DIRAC_PCODE_INTRA_REF_PICT  = 0xCC,\n    DIRAC_PCODE_MAGIC           = 0x42424344,\n};\n\ntypedef struct DiracVersionInfo {\n    int major;\n    int minor;\n} DiracVersionInfo;\n\ntypedef struct AVDiracSeqHeader {\n    unsigned width;\n    unsigned height;\n    uint8_t chroma_format;          ///< 0: 444  1: 422  2: 420\n\n    uint8_t interlaced;\n    uint8_t top_field_first;\n\n    uint8_t frame_rate_index;       ///< index into dirac_frame_rate[]\n    uint8_t aspect_ratio_index;     ///< index into dirac_aspect_ratio[]\n\n    uint16_t clean_width;\n    uint16_t clean_height;\n    uint16_t clean_left_offset;\n    uint16_t clean_right_offset;\n\n    uint8_t pixel_range_index;      ///< index into dirac_pixel_range_presets[]\n    uint8_t color_spec_index;       ///< index into dirac_color_spec_presets[]\n\n    int profile;\n    int level;\n\n    AVRational framerate;\n    AVRational sample_aspect_ratio;\n\n    enum AVPixelFormat pix_fmt;\n    enum AVColorRange color_range;\n    enum AVColorPrimaries color_primaries;\n    enum AVColorTransferCharacteristic color_trc;\n    enum AVColorSpace colorspace;\n\n    DiracVersionInfo version;\n    int bit_depth;\n} AVDiracSeqHeader;\n\n/**\n * Parse a Dirac sequence header.\n *\n * @param dsh this function will allocate and fill an AVDiracSeqHeader struct\n *            and write it into this pointer. The caller must free it with\n *            av_free().\n * @param buf the data buffer\n * @param buf_size the size of the data buffer in bytes\n * @param log_ctx if non-NULL, this function will log errors here\n * @return 0 on success, a negative AVERROR code on failure\n */\nint av_dirac_parse_sequence_header(AVDiracSeqHeader **dsh,\n                                   const uint8_t *buf, size_t buf_size,\n                                   void *log_ctx);\n\n#endif /* AVCODEC_DIRAC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/dv_profile.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_DV_PROFILE_H\n#define AVCODEC_DV_PROFILE_H\n\n#include <stdint.h>\n\n#include \"libavutil/pixfmt.h\"\n#include \"libavutil/rational.h\"\n\n/* minimum number of bytes to read from a DV stream in order to\n * determine the profile */\n#define DV_PROFILE_BYTES (6 * 80) /* 6 DIF blocks */\n\n\n/*\n * AVDVProfile is used to express the differences between various\n * DV flavors. For now it's primarily used for differentiating\n * 525/60 and 625/50, but the plans are to use it for various\n * DV specs as well (e.g. SMPTE314M vs. IEC 61834).\n */\ntypedef struct AVDVProfile {\n    int              dsf;                   /* value of the dsf in the DV header */\n    int              video_stype;           /* stype for VAUX source pack */\n    int              frame_size;            /* total size of one frame in bytes */\n    int              difseg_size;           /* number of DIF segments per DIF channel */\n    int              n_difchan;             /* number of DIF channels per frame */\n    AVRational       time_base;             /* 1/framerate */\n    int              ltc_divisor;           /* FPS from the LTS standpoint */\n    int              height;                /* picture height in pixels */\n    int              width;                 /* picture width in pixels */\n    AVRational       sar[2];                /* sample aspect ratios for 4:3 and 16:9 */\n    enum AVPixelFormat pix_fmt;             /* picture pixel format */\n    int              bpm;                   /* blocks per macroblock */\n    const uint8_t   *block_sizes;           /* AC block sizes, in bits */\n    int              audio_stride;          /* size of audio_shuffle table */\n    int              audio_min_samples[3];  /* min amount of audio samples */\n                                            /* for 48kHz, 44.1kHz and 32kHz */\n    int              audio_samples_dist[5]; /* how many samples are supposed to be */\n                                            /* in each frame in a 5 frames window */\n    const uint8_t  (*audio_shuffle)[9];     /* PCM shuffling table */\n} AVDVProfile;\n\n/**\n * Get a DV profile for the provided compressed frame.\n *\n * @param sys the profile used for the previous frame, may be NULL\n * @param frame the compressed data buffer\n * @param buf_size size of the buffer in bytes\n * @return the DV profile for the supplied data or NULL on failure\n */\nconst AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys,\n                                       const uint8_t *frame, unsigned buf_size);\n\n/**\n * Get a DV profile for the provided stream parameters.\n */\nconst AVDVProfile *av_dv_codec_profile(int width, int height, enum AVPixelFormat pix_fmt);\n\n/**\n * Get a DV profile for the provided stream parameters.\n * The frame rate is used as a best-effort parameter.\n */\nconst AVDVProfile *av_dv_codec_profile2(int width, int height, enum AVPixelFormat pix_fmt, AVRational frame_rate);\n\n#endif /* AVCODEC_DV_PROFILE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/dxva2.h",
    "content": "/*\n * DXVA2 HW acceleration\n *\n * copyright (c) 2009 Laurent Aimar\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_DXVA2_H\n#define AVCODEC_DXVA2_H\n\n/**\n * @file\n * @ingroup lavc_codec_hwaccel_dxva2\n * Public libavcodec DXVA2 header.\n */\n\n#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602\n#undef _WIN32_WINNT\n#define _WIN32_WINNT 0x0602\n#endif\n\n#include <stdint.h>\n#include <d3d9.h>\n#include <dxva2api.h>\n\n/**\n * @defgroup lavc_codec_hwaccel_dxva2 DXVA2\n * @ingroup lavc_codec_hwaccel\n *\n * @{\n */\n\n#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards\n#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO    2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface\n\n/**\n * This structure is used to provides the necessary configurations and data\n * to the DXVA2 FFmpeg HWAccel implementation.\n *\n * The application must make it available as AVCodecContext.hwaccel_context.\n */\nstruct dxva_context {\n    /**\n     * DXVA2 decoder object\n     */\n    IDirectXVideoDecoder *decoder;\n\n    /**\n     * DXVA2 configuration used to create the decoder\n     */\n    const DXVA2_ConfigPictureDecode *cfg;\n\n    /**\n     * The number of surface in the surface array\n     */\n    unsigned surface_count;\n\n    /**\n     * The array of Direct3D surfaces used to create the decoder\n     */\n    LPDIRECT3DSURFACE9 *surface;\n\n    /**\n     * A bit field configuring the workarounds needed for using the decoder\n     */\n    uint64_t workaround;\n\n    /**\n     * Private to the FFmpeg AVHWAccel implementation\n     */\n    unsigned report_id;\n};\n\n/**\n * @}\n */\n\n#endif /* AVCODEC_DXVA2_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/jni.h",
    "content": "/*\n * JNI public API functions\n *\n * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_JNI_H\n#define AVCODEC_JNI_H\n\n/*\n * Manually set a Java virtual machine which will be used to retrieve the JNI\n * environment. Once a Java VM is set it cannot be changed afterwards, meaning\n * you can call multiple times av_jni_set_java_vm with the same Java VM pointer\n * however it will error out if you try to set a different Java VM.\n *\n * @param vm Java virtual machine\n * @param log_ctx context used for logging, can be NULL\n * @return 0 on success, < 0 otherwise\n */\nint av_jni_set_java_vm(void *vm, void *log_ctx);\n\n/*\n * Get the Java virtual machine which has been set with av_jni_set_java_vm.\n *\n * @param vm Java virtual machine\n * @return a pointer to the Java virtual machine\n */\nvoid *av_jni_get_java_vm(void *log_ctx);\n\n#endif /* AVCODEC_JNI_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/mediacodec.h",
    "content": "/*\n * Android MediaCodec public API\n *\n * Copyright (c) 2016 Matthieu Bouron <matthieu.bouron stupeflix.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_MEDIACODEC_H\n#define AVCODEC_MEDIACODEC_H\n\n#include \"libavcodec/avcodec.h\"\n\n/**\n * This structure holds a reference to a android/view/Surface object that will\n * be used as output by the decoder.\n *\n */\ntypedef struct AVMediaCodecContext {\n\n    /**\n     * android/view/Surface object reference.\n     */\n    void *surface;\n\n} AVMediaCodecContext;\n\n/**\n * Allocate and initialize a MediaCodec context.\n *\n * When decoding with MediaCodec is finished, the caller must free the\n * MediaCodec context with av_mediacodec_default_free.\n *\n * @return a pointer to a newly allocated AVMediaCodecContext on success, NULL otherwise\n */\nAVMediaCodecContext *av_mediacodec_alloc_context(void);\n\n/**\n * Convenience function that sets up the MediaCodec context.\n *\n * @param avctx codec context\n * @param ctx MediaCodec context to initialize\n * @param surface reference to an android/view/Surface\n * @return 0 on success, < 0 otherwise\n */\nint av_mediacodec_default_init(AVCodecContext *avctx, AVMediaCodecContext *ctx, void *surface);\n\n/**\n * This function must be called to free the MediaCodec context initialized with\n * av_mediacodec_default_init().\n *\n * @param avctx codec context\n */\nvoid av_mediacodec_default_free(AVCodecContext *avctx);\n\n/**\n * Opaque structure representing a MediaCodec buffer to render.\n */\ntypedef struct MediaCodecBuffer AVMediaCodecBuffer;\n\n/**\n * Release a MediaCodec buffer and render it to the surface that is associated\n * with the decoder. This function should only be called once on a given\n * buffer, once released the underlying buffer returns to the codec, thus\n * subsequent calls to this function will have no effect.\n *\n * @param buffer the buffer to render\n * @param render 1 to release and render the buffer to the surface or 0 to\n * discard the buffer\n * @return 0 on success, < 0 otherwise\n */\nint av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render);\n\n/**\n * Release a MediaCodec buffer and render it at the given time to the surface\n * that is associated with the decoder. The timestamp must be within one second\n * of the current java/lang/System#nanoTime() (which is implemented using\n * CLOCK_MONOTONIC on Android). See the Android MediaCodec documentation\n * of android/media/MediaCodec#releaseOutputBuffer(int,long) for more details.\n *\n * @param buffer the buffer to render\n * @param time timestamp in nanoseconds of when to render the buffer\n * @return 0 on success, < 0 otherwise\n */\nint av_mediacodec_render_buffer_at_time(AVMediaCodecBuffer *buffer, int64_t time);\n\n#endif /* AVCODEC_MEDIACODEC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/packet.h",
    "content": "/*\n * AVPacket public API\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_PACKET_H\n#define AVCODEC_PACKET_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"libavutil/attributes.h\"\n#include \"libavutil/buffer.h\"\n#include \"libavutil/dict.h\"\n#include \"libavutil/rational.h\"\n#include \"libavutil/version.h\"\n\n#include \"libavcodec/version_major.h\"\n\n/**\n * @defgroup lavc_packet AVPacket\n *\n * Types and functions for working with AVPacket.\n * @{\n */\nenum AVPacketSideDataType {\n    /**\n     * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE\n     * bytes worth of palette. This side data signals that a new palette is\n     * present.\n     */\n    AV_PKT_DATA_PALETTE,\n\n    /**\n     * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format\n     * that the extradata buffer was changed and the receiving side should\n     * act upon it appropriately. The new extradata is embedded in the side\n     * data buffer and should be immediately used for processing the current\n     * frame or packet.\n     */\n    AV_PKT_DATA_NEW_EXTRADATA,\n\n    /**\n     * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows:\n     * @code\n     * u32le param_flags\n     * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT)\n     *     s32le channel_count\n     * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT)\n     *     u64le channel_layout\n     * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE)\n     *     s32le sample_rate\n     * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS)\n     *     s32le width\n     *     s32le height\n     * @endcode\n     */\n    AV_PKT_DATA_PARAM_CHANGE,\n\n    /**\n     * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of\n     * structures with info about macroblocks relevant to splitting the\n     * packet into smaller packets on macroblock edges (e.g. as for RFC 2190).\n     * That is, it does not necessarily contain info about all macroblocks,\n     * as long as the distance between macroblocks in the info is smaller\n     * than the target payload size.\n     * Each MB info structure is 12 bytes, and is laid out as follows:\n     * @code\n     * u32le bit offset from the start of the packet\n     * u8    current quantizer at the start of the macroblock\n     * u8    GOB number\n     * u16le macroblock address within the GOB\n     * u8    horizontal MV predictor\n     * u8    vertical MV predictor\n     * u8    horizontal MV predictor for block number 3\n     * u8    vertical MV predictor for block number 3\n     * @endcode\n     */\n    AV_PKT_DATA_H263_MB_INFO,\n\n    /**\n     * This side data should be associated with an audio stream and contains\n     * ReplayGain information in form of the AVReplayGain struct.\n     */\n    AV_PKT_DATA_REPLAYGAIN,\n\n    /**\n     * This side data contains a 3x3 transformation matrix describing an affine\n     * transformation that needs to be applied to the decoded video frames for\n     * correct presentation.\n     *\n     * See libavutil/display.h for a detailed description of the data.\n     */\n    AV_PKT_DATA_DISPLAYMATRIX,\n\n    /**\n     * This side data should be associated with a video stream and contains\n     * Stereoscopic 3D information in form of the AVStereo3D struct.\n     */\n    AV_PKT_DATA_STEREO3D,\n\n    /**\n     * This side data should be associated with an audio stream and corresponds\n     * to enum AVAudioServiceType.\n     */\n    AV_PKT_DATA_AUDIO_SERVICE_TYPE,\n\n    /**\n     * This side data contains quality related information from the encoder.\n     * @code\n     * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad).\n     * u8    picture type\n     * u8    error count\n     * u16   reserved\n     * u64le[error count] sum of squared differences between encoder in and output\n     * @endcode\n     */\n    AV_PKT_DATA_QUALITY_STATS,\n\n    /**\n     * This side data contains an integer value representing the stream index\n     * of a \"fallback\" track.  A fallback track indicates an alternate\n     * track to use when the current track can not be decoded for some reason.\n     * e.g. no decoder available for codec.\n     */\n    AV_PKT_DATA_FALLBACK_TRACK,\n\n    /**\n     * This side data corresponds to the AVCPBProperties struct.\n     */\n    AV_PKT_DATA_CPB_PROPERTIES,\n\n    /**\n     * Recommmends skipping the specified number of samples\n     * @code\n     * u32le number of samples to skip from start of this packet\n     * u32le number of samples to skip from end of this packet\n     * u8    reason for start skip\n     * u8    reason for end   skip (0=padding silence, 1=convergence)\n     * @endcode\n     */\n    AV_PKT_DATA_SKIP_SAMPLES,\n\n    /**\n     * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that\n     * the packet may contain \"dual mono\" audio specific to Japanese DTV\n     * and if it is true, recommends only the selected channel to be used.\n     * @code\n     * u8    selected channels (0=mail/left, 1=sub/right, 2=both)\n     * @endcode\n     */\n    AV_PKT_DATA_JP_DUALMONO,\n\n    /**\n     * A list of zero terminated key/value strings. There is no end marker for\n     * the list, so it is required to rely on the side data size to stop.\n     */\n    AV_PKT_DATA_STRINGS_METADATA,\n\n    /**\n     * Subtitle event position\n     * @code\n     * u32le x1\n     * u32le y1\n     * u32le x2\n     * u32le y2\n     * @endcode\n     */\n    AV_PKT_DATA_SUBTITLE_POSITION,\n\n    /**\n     * Data found in BlockAdditional element of matroska container. There is\n     * no end marker for the data, so it is required to rely on the side data\n     * size to recognize the end. 8 byte id (as found in BlockAddId) followed\n     * by data.\n     */\n    AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,\n\n    /**\n     * The optional first identifier line of a WebVTT cue.\n     */\n    AV_PKT_DATA_WEBVTT_IDENTIFIER,\n\n    /**\n     * The optional settings (rendering instructions) that immediately\n     * follow the timestamp specifier of a WebVTT cue.\n     */\n    AV_PKT_DATA_WEBVTT_SETTINGS,\n\n    /**\n     * A list of zero terminated key/value strings. There is no end marker for\n     * the list, so it is required to rely on the side data size to stop. This\n     * side data includes updated metadata which appeared in the stream.\n     */\n    AV_PKT_DATA_METADATA_UPDATE,\n\n    /**\n     * MPEGTS stream ID as uint8_t, this is required to pass the stream ID\n     * information from the demuxer to the corresponding muxer.\n     */\n    AV_PKT_DATA_MPEGTS_STREAM_ID,\n\n    /**\n     * Mastering display metadata (based on SMPTE-2086:2014). This metadata\n     * should be associated with a video stream and contains data in the form\n     * of the AVMasteringDisplayMetadata struct.\n     */\n    AV_PKT_DATA_MASTERING_DISPLAY_METADATA,\n\n    /**\n     * This side data should be associated with a video stream and corresponds\n     * to the AVSphericalMapping structure.\n     */\n    AV_PKT_DATA_SPHERICAL,\n\n    /**\n     * Content light level (based on CTA-861.3). This metadata should be\n     * associated with a video stream and contains data in the form of the\n     * AVContentLightMetadata struct.\n     */\n    AV_PKT_DATA_CONTENT_LIGHT_LEVEL,\n\n    /**\n     * ATSC A53 Part 4 Closed Captions. This metadata should be associated with\n     * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data.\n     * The number of bytes of CC data is AVPacketSideData.size.\n     */\n    AV_PKT_DATA_A53_CC,\n\n    /**\n     * This side data is encryption initialization data.\n     * The format is not part of ABI, use av_encryption_init_info_* methods to\n     * access.\n     */\n    AV_PKT_DATA_ENCRYPTION_INIT_INFO,\n\n    /**\n     * This side data contains encryption info for how to decrypt the packet.\n     * The format is not part of ABI, use av_encryption_info_* methods to access.\n     */\n    AV_PKT_DATA_ENCRYPTION_INFO,\n\n    /**\n     * Active Format Description data consisting of a single byte as specified\n     * in ETSI TS 101 154 using AVActiveFormatDescription enum.\n     */\n    AV_PKT_DATA_AFD,\n\n    /**\n     * Producer Reference Time data corresponding to the AVProducerReferenceTime struct,\n     * usually exported by some encoders (on demand through the prft flag set in the\n     * AVCodecContext export_side_data field).\n     */\n    AV_PKT_DATA_PRFT,\n\n    /**\n     * ICC profile data consisting of an opaque octet buffer following the\n     * format described by ISO 15076-1.\n     */\n    AV_PKT_DATA_ICC_PROFILE,\n\n    /**\n     * DOVI configuration\n     * ref:\n     * dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2, section 2.2\n     * dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2, section 3.3\n     * Tags are stored in struct AVDOVIDecoderConfigurationRecord.\n     */\n    AV_PKT_DATA_DOVI_CONF,\n\n    /**\n     * Timecode which conforms to SMPTE ST 12-1:2014. The data is an array of 4 uint32_t\n     * where the first uint32_t describes how many (1-3) of the other timecodes are used.\n     * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum()\n     * function in libavutil/timecode.h.\n     */\n    AV_PKT_DATA_S12M_TIMECODE,\n\n    /**\n     * HDR10+ dynamic metadata associated with a video frame. The metadata is in\n     * the form of the AVDynamicHDRPlus struct and contains\n     * information for color volume transform - application 4 of\n     * SMPTE 2094-40:2016 standard.\n     */\n    AV_PKT_DATA_DYNAMIC_HDR10_PLUS,\n\n    /**\n     * The number of side data types.\n     * This is not part of the public API/ABI in the sense that it may\n     * change when new side data types are added.\n     * This must stay the last enum value.\n     * If its value becomes huge, some code using it\n     * needs to be updated as it assumes it to be smaller than other limits.\n     */\n    AV_PKT_DATA_NB\n};\n\n#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED\n\ntypedef struct AVPacketSideData {\n    uint8_t *data;\n    size_t   size;\n    enum AVPacketSideDataType type;\n} AVPacketSideData;\n\n/**\n * This structure stores compressed data. It is typically exported by demuxers\n * and then passed as input to decoders, or received as output from encoders and\n * then passed to muxers.\n *\n * For video, it should typically contain one compressed frame. For audio it may\n * contain several compressed frames. Encoders are allowed to output empty\n * packets, with no compressed data, containing only side data\n * (e.g. to update some stream parameters at the end of encoding).\n *\n * The semantics of data ownership depends on the buf field.\n * If it is set, the packet data is dynamically allocated and is\n * valid indefinitely until a call to av_packet_unref() reduces the\n * reference count to 0.\n *\n * If the buf field is not set av_packet_ref() would make a copy instead\n * of increasing the reference count.\n *\n * The side data is always allocated with av_malloc(), copied by\n * av_packet_ref() and freed by av_packet_unref().\n *\n * sizeof(AVPacket) being a part of the public ABI is deprecated. once\n * av_init_packet() is removed, new packets will only be able to be allocated\n * with av_packet_alloc(), and new fields may be added to the end of the struct\n * with a minor bump.\n *\n * @see av_packet_alloc\n * @see av_packet_ref\n * @see av_packet_unref\n */\ntypedef struct AVPacket {\n    /**\n     * A reference to the reference-counted buffer where the packet data is\n     * stored.\n     * May be NULL, then the packet data is not reference-counted.\n     */\n    AVBufferRef *buf;\n    /**\n     * Presentation timestamp in AVStream->time_base units; the time at which\n     * the decompressed packet will be presented to the user.\n     * Can be AV_NOPTS_VALUE if it is not stored in the file.\n     * pts MUST be larger or equal to dts as presentation cannot happen before\n     * decompression, unless one wants to view hex dumps. Some formats misuse\n     * the terms dts and pts/cts to mean something different. Such timestamps\n     * must be converted to true pts/dts before they are stored in AVPacket.\n     */\n    int64_t pts;\n    /**\n     * Decompression timestamp in AVStream->time_base units; the time at which\n     * the packet is decompressed.\n     * Can be AV_NOPTS_VALUE if it is not stored in the file.\n     */\n    int64_t dts;\n    uint8_t *data;\n    int   size;\n    int   stream_index;\n    /**\n     * A combination of AV_PKT_FLAG values\n     */\n    int   flags;\n    /**\n     * Additional packet data that can be provided by the container.\n     * Packet can contain several types of side information.\n     */\n    AVPacketSideData *side_data;\n    int side_data_elems;\n\n    /**\n     * Duration of this packet in AVStream->time_base units, 0 if unknown.\n     * Equals next_pts - this_pts in presentation order.\n     */\n    int64_t duration;\n\n    int64_t pos;                            ///< byte position in stream, -1 if unknown\n\n    /**\n     * for some private data of the user\n     */\n    void *opaque;\n\n    /**\n     * AVBufferRef for free use by the API user. FFmpeg will never check the\n     * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when\n     * the packet is unreferenced. av_packet_copy_props() calls create a new\n     * reference with av_buffer_ref() for the target packet's opaque_ref field.\n     *\n     * This is unrelated to the opaque field, although it serves a similar\n     * purpose.\n     */\n    AVBufferRef *opaque_ref;\n\n    /**\n     * Time base of the packet's timestamps.\n     * In the future, this field may be set on packets output by encoders or\n     * demuxers, but its value will be by default ignored on input to decoders\n     * or muxers.\n     */\n    AVRational time_base;\n} AVPacket;\n\n#if FF_API_INIT_PACKET\nattribute_deprecated\ntypedef struct AVPacketList {\n    AVPacket pkt;\n    struct AVPacketList *next;\n} AVPacketList;\n#endif\n\n#define AV_PKT_FLAG_KEY     0x0001 ///< The packet contains a keyframe\n#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted\n/**\n * Flag is used to discard packets which are required to maintain valid\n * decoder state but are not required for output and should be dropped\n * after decoding.\n **/\n#define AV_PKT_FLAG_DISCARD   0x0004\n/**\n * The packet comes from a trusted source.\n *\n * Otherwise-unsafe constructs such as arbitrary pointers to data\n * outside the packet may be followed.\n */\n#define AV_PKT_FLAG_TRUSTED   0x0008\n/**\n * Flag is used to indicate packets that contain frames that can\n * be discarded by the decoder.  I.e. Non-reference frames.\n */\n#define AV_PKT_FLAG_DISPOSABLE 0x0010\n\nenum AVSideDataParamChangeFlags {\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * @deprecated those are not used by any decoder\n     */\n    AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT  = 0x0001,\n    AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002,\n#endif\n    AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE    = 0x0004,\n    AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS     = 0x0008,\n};\n\n/**\n * Allocate an AVPacket and set its fields to default values.  The resulting\n * struct must be freed using av_packet_free().\n *\n * @return An AVPacket filled with default values or NULL on failure.\n *\n * @note this only allocates the AVPacket itself, not the data buffers. Those\n * must be allocated through other means such as av_new_packet.\n *\n * @see av_new_packet\n */\nAVPacket *av_packet_alloc(void);\n\n/**\n * Create a new packet that references the same data as src.\n *\n * This is a shortcut for av_packet_alloc()+av_packet_ref().\n *\n * @return newly created AVPacket on success, NULL on error.\n *\n * @see av_packet_alloc\n * @see av_packet_ref\n */\nAVPacket *av_packet_clone(const AVPacket *src);\n\n/**\n * Free the packet, if the packet is reference counted, it will be\n * unreferenced first.\n *\n * @param pkt packet to be freed. The pointer will be set to NULL.\n * @note passing NULL is a no-op.\n */\nvoid av_packet_free(AVPacket **pkt);\n\n#if FF_API_INIT_PACKET\n/**\n * Initialize optional fields of a packet with default values.\n *\n * Note, this does not touch the data and size members, which have to be\n * initialized separately.\n *\n * @param pkt packet\n *\n * @see av_packet_alloc\n * @see av_packet_unref\n *\n * @deprecated This function is deprecated. Once it's removed,\n               sizeof(AVPacket) will not be a part of the ABI anymore.\n */\nattribute_deprecated\nvoid av_init_packet(AVPacket *pkt);\n#endif\n\n/**\n * Allocate the payload of a packet and initialize its fields with\n * default values.\n *\n * @param pkt packet\n * @param size wanted payload size\n * @return 0 if OK, AVERROR_xxx otherwise\n */\nint av_new_packet(AVPacket *pkt, int size);\n\n/**\n * Reduce packet size, correctly zeroing padding\n *\n * @param pkt packet\n * @param size new size\n */\nvoid av_shrink_packet(AVPacket *pkt, int size);\n\n/**\n * Increase packet size, correctly zeroing padding\n *\n * @param pkt packet\n * @param grow_by number of bytes by which to increase the size of the packet\n */\nint av_grow_packet(AVPacket *pkt, int grow_by);\n\n/**\n * Initialize a reference-counted packet from av_malloc()ed data.\n *\n * @param pkt packet to be initialized. This function will set the data, size,\n *        and buf fields, all others are left untouched.\n * @param data Data allocated by av_malloc() to be used as packet data. If this\n *        function returns successfully, the data is owned by the underlying AVBuffer.\n *        The caller may not access the data through other means.\n * @param size size of data in bytes, without the padding. I.e. the full buffer\n *        size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE.\n *\n * @return 0 on success, a negative AVERROR on error\n */\nint av_packet_from_data(AVPacket *pkt, uint8_t *data, int size);\n\n/**\n * Allocate new information of a packet.\n *\n * @param pkt packet\n * @param type side information type\n * @param size side information size\n * @return pointer to fresh allocated data or NULL otherwise\n */\nuint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type,\n                                 size_t size);\n\n/**\n * Wrap an existing array as a packet side data.\n *\n * @param pkt packet\n * @param type side information type\n * @param data the side data array. It must be allocated with the av_malloc()\n *             family of functions. The ownership of the data is transferred to\n *             pkt.\n * @param size side information size\n * @return a non-negative number on success, a negative AVERROR code on\n *         failure. On failure, the packet is unchanged and the data remains\n *         owned by the caller.\n */\nint av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type,\n                            uint8_t *data, size_t size);\n\n/**\n * Shrink the already allocated side data buffer\n *\n * @param pkt packet\n * @param type side information type\n * @param size new side information size\n * @return 0 on success, < 0 on failure\n */\nint av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,\n                               size_t size);\n\n/**\n * Get side information from packet.\n *\n * @param pkt packet\n * @param type desired side information type\n * @param size If supplied, *size will be set to the size of the side data\n *             or to zero if the desired side data is not present.\n * @return pointer to data if present or NULL otherwise\n */\nuint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type,\n                                 size_t *size);\n\nconst char *av_packet_side_data_name(enum AVPacketSideDataType type);\n\n/**\n * Pack a dictionary for use in side_data.\n *\n * @param dict The dictionary to pack.\n * @param size pointer to store the size of the returned data\n * @return pointer to data if successful, NULL otherwise\n */\nuint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size);\n/**\n * Unpack a dictionary from side_data.\n *\n * @param data data from side_data\n * @param size size of the data\n * @param dict the metadata storage dictionary\n * @return 0 on success, < 0 on failure\n */\nint av_packet_unpack_dictionary(const uint8_t *data, size_t size,\n                                AVDictionary **dict);\n\n/**\n * Convenience function to free all the side data stored.\n * All the other fields stay untouched.\n *\n * @param pkt packet\n */\nvoid av_packet_free_side_data(AVPacket *pkt);\n\n/**\n * Setup a new reference to the data described by a given packet\n *\n * If src is reference-counted, setup dst as a new reference to the\n * buffer in src. Otherwise allocate a new buffer in dst and copy the\n * data from src into it.\n *\n * All the other fields are copied from src.\n *\n * @see av_packet_unref\n *\n * @param dst Destination packet. Will be completely overwritten.\n * @param src Source packet\n *\n * @return 0 on success, a negative AVERROR on error. On error, dst\n *         will be blank (as if returned by av_packet_alloc()).\n */\nint av_packet_ref(AVPacket *dst, const AVPacket *src);\n\n/**\n * Wipe the packet.\n *\n * Unreference the buffer referenced by the packet and reset the\n * remaining packet fields to their default values.\n *\n * @param pkt The packet to be unreferenced.\n */\nvoid av_packet_unref(AVPacket *pkt);\n\n/**\n * Move every field in src to dst and reset src.\n *\n * @see av_packet_unref\n *\n * @param src Source packet, will be reset\n * @param dst Destination packet\n */\nvoid av_packet_move_ref(AVPacket *dst, AVPacket *src);\n\n/**\n * Copy only \"properties\" fields from src to dst.\n *\n * Properties for the purpose of this function are all the fields\n * beside those related to the packet data (buf, data, size)\n *\n * @param dst Destination packet\n * @param src Source packet\n *\n * @return 0 on success AVERROR on failure.\n */\nint av_packet_copy_props(AVPacket *dst, const AVPacket *src);\n\n/**\n * Ensure the data described by a given packet is reference counted.\n *\n * @note This function does not ensure that the reference will be writable.\n *       Use av_packet_make_writable instead for that purpose.\n *\n * @see av_packet_ref\n * @see av_packet_make_writable\n *\n * @param pkt packet whose data should be made reference counted.\n *\n * @return 0 on success, a negative AVERROR on error. On failure, the\n *         packet is unchanged.\n */\nint av_packet_make_refcounted(AVPacket *pkt);\n\n/**\n * Create a writable reference for the data described by a given packet,\n * avoiding data copy if possible.\n *\n * @param pkt Packet whose data should be made writable.\n *\n * @return 0 on success, a negative AVERROR on failure. On failure, the\n *         packet is unchanged.\n */\nint av_packet_make_writable(AVPacket *pkt);\n\n/**\n * Convert valid timing fields (timestamps / durations) in a packet from one\n * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be\n * ignored.\n *\n * @param pkt packet on which the conversion will be performed\n * @param tb_src source timebase, in which the timing fields in pkt are\n *               expressed\n * @param tb_dst destination timebase, to which the timing fields will be\n *               converted\n */\nvoid av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);\n\n/**\n * @}\n */\n\n#endif // AVCODEC_PACKET_H\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/qsv.h",
    "content": "/*\n * Intel MediaSDK QSV public API\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_QSV_H\n#define AVCODEC_QSV_H\n\n#include <mfx/mfxvideo.h>\n\n#include \"libavutil/buffer.h\"\n\n/**\n * This struct is used for communicating QSV parameters between libavcodec and\n * the caller. It is managed by the caller and must be assigned to\n * AVCodecContext.hwaccel_context.\n * - decoding: hwaccel_context must be set on return from the get_format()\n *             callback\n * - encoding: hwaccel_context must be set before avcodec_open2()\n */\ntypedef struct AVQSVContext {\n    /**\n     * If non-NULL, the session to use for encoding or decoding.\n     * Otherwise, libavcodec will try to create an internal session.\n     */\n    mfxSession session;\n\n    /**\n     * The IO pattern to use.\n     */\n    int iopattern;\n\n    /**\n     * Extra buffers to pass to encoder or decoder initialization.\n     */\n    mfxExtBuffer **ext_buffers;\n    int         nb_ext_buffers;\n\n    /**\n     * Encoding only. If this field is set to non-zero by the caller, libavcodec\n     * will create an mfxExtOpaqueSurfaceAlloc extended buffer and pass it to\n     * the encoder initialization. This only makes sense if iopattern is also\n     * set to MFX_IOPATTERN_IN_OPAQUE_MEMORY.\n     *\n     * The number of allocated opaque surfaces will be the sum of the number\n     * required by the encoder and the user-provided value nb_opaque_surfaces.\n     * The array of the opaque surfaces will be exported to the caller through\n     * the opaque_surfaces field.\n     */\n    int opaque_alloc;\n\n    /**\n     * Encoding only, and only if opaque_alloc is set to non-zero. Before\n     * calling avcodec_open2(), the caller should set this field to the number\n     * of extra opaque surfaces to allocate beyond what is required by the\n     * encoder.\n     *\n     * On return from avcodec_open2(), this field will be set by libavcodec to\n     * the total number of allocated opaque surfaces.\n     */\n    int nb_opaque_surfaces;\n\n    /**\n     * Encoding only, and only if opaque_alloc is set to non-zero. On return\n     * from avcodec_open2(), this field will be used by libavcodec to export the\n     * array of the allocated opaque surfaces to the caller, so they can be\n     * passed to other parts of the pipeline.\n     *\n     * The buffer reference exported here is owned and managed by libavcodec,\n     * the callers should make their own reference with av_buffer_ref() and free\n     * it with av_buffer_unref() when it is no longer needed.\n     *\n     * The buffer data is an nb_opaque_surfaces-sized array of mfxFrameSurface1.\n     */\n    AVBufferRef *opaque_surfaces;\n\n    /**\n     * Encoding only, and only if opaque_alloc is set to non-zero. On return\n     * from avcodec_open2(), this field will be set to the surface type used in\n     * the opaque allocation request.\n     */\n    int opaque_alloc_type;\n} AVQSVContext;\n\n/**\n * Allocate a new context.\n *\n * It must be freed by the caller with av_free().\n */\nAVQSVContext *av_qsv_alloc_context(void);\n\n#endif /* AVCODEC_QSV_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/vdpau.h",
    "content": "/*\n * The Video Decode and Presentation API for UNIX (VDPAU) is used for\n * hardware-accelerated decoding of MPEG-1/2, H.264 and VC-1.\n *\n * Copyright (C) 2008 NVIDIA\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_VDPAU_H\n#define AVCODEC_VDPAU_H\n\n/**\n * @file\n * @ingroup lavc_codec_hwaccel_vdpau\n * Public libavcodec VDPAU header.\n */\n\n\n/**\n * @defgroup lavc_codec_hwaccel_vdpau VDPAU Decoder and Renderer\n * @ingroup lavc_codec_hwaccel\n *\n * VDPAU hardware acceleration has two modules\n * - VDPAU decoding\n * - VDPAU presentation\n *\n * The VDPAU decoding module parses all headers using FFmpeg\n * parsing mechanisms and uses VDPAU for the actual decoding.\n *\n * As per the current implementation, the actual decoding\n * and rendering (API calls) are done as part of the VDPAU\n * presentation (vo_vdpau.c) module.\n *\n * @{\n */\n\n#include <vdpau/vdpau.h>\n\n#include \"libavutil/avconfig.h\"\n#include \"libavutil/attributes.h\"\n\n#include \"avcodec.h\"\n\nstruct AVCodecContext;\nstruct AVFrame;\n\ntypedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,\n                               const VdpPictureInfo *, uint32_t,\n                               const VdpBitstreamBuffer *);\n\n/**\n * This structure is used to share data between the libavcodec library and\n * the client video application.\n * The user shall allocate the structure via the av_alloc_vdpau_hwaccel\n * function and make it available as\n * AVCodecContext.hwaccel_context. Members can be set by the user once\n * during initialization or through each AVCodecContext.get_buffer()\n * function call. In any case, they must be valid prior to calling\n * decoding functions.\n *\n * The size of this structure is not a part of the public ABI and must not\n * be used outside of libavcodec. Use av_vdpau_alloc_context() to allocate an\n * AVVDPAUContext.\n */\ntypedef struct AVVDPAUContext {\n    /**\n     * VDPAU decoder handle\n     *\n     * Set by user.\n     */\n    VdpDecoder decoder;\n\n    /**\n     * VDPAU decoder render callback\n     *\n     * Set by the user.\n     */\n    VdpDecoderRender *render;\n\n    AVVDPAU_Render2 render2;\n} AVVDPAUContext;\n\n/**\n * @brief allocation function for AVVDPAUContext\n *\n * Allows extending the struct without breaking API/ABI\n */\nAVVDPAUContext *av_alloc_vdpaucontext(void);\n\nAVVDPAU_Render2 av_vdpau_hwaccel_get_render2(const AVVDPAUContext *);\nvoid av_vdpau_hwaccel_set_render2(AVVDPAUContext *, AVVDPAU_Render2);\n\n/**\n * Associate a VDPAU device with a codec context for hardware acceleration.\n * This function is meant to be called from the get_format() codec callback,\n * or earlier. It can also be called after avcodec_flush_buffers() to change\n * the underlying VDPAU device mid-stream (e.g. to recover from non-transparent\n * display preemption).\n *\n * @note get_format() must return AV_PIX_FMT_VDPAU if this function completes\n * successfully.\n *\n * @param avctx decoding context whose get_format() callback is invoked\n * @param device VDPAU device handle to use for hardware acceleration\n * @param get_proc_address VDPAU device driver\n * @param flags zero of more OR'd AV_HWACCEL_FLAG_* flags\n *\n * @return 0 on success, an AVERROR code on failure.\n */\nint av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,\n                          VdpGetProcAddress *get_proc_address, unsigned flags);\n\n/**\n * Gets the parameters to create an adequate VDPAU video surface for the codec\n * context using VDPAU hardware decoding acceleration.\n *\n * @note Behavior is undefined if the context was not successfully bound to a\n * VDPAU device using av_vdpau_bind_context().\n *\n * @param avctx the codec context being used for decoding the stream\n * @param type storage space for the VDPAU video surface chroma type\n *              (or NULL to ignore)\n * @param width storage space for the VDPAU video surface pixel width\n *              (or NULL to ignore)\n * @param height storage space for the VDPAU video surface pixel height\n *              (or NULL to ignore)\n *\n * @return 0 on success, a negative AVERROR code on failure.\n */\nint av_vdpau_get_surface_parameters(AVCodecContext *avctx, VdpChromaType *type,\n                                    uint32_t *width, uint32_t *height);\n\n/**\n * Allocate an AVVDPAUContext.\n *\n * @return Newly-allocated AVVDPAUContext or NULL on failure.\n */\nAVVDPAUContext *av_vdpau_alloc_context(void);\n\n/* @}*/\n\n#endif /* AVCODEC_VDPAU_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/version.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_VERSION_H\n#define AVCODEC_VERSION_H\n\n/**\n * @file\n * @ingroup libavc\n * Libavcodec version macros.\n */\n\n#include \"libavutil/version.h\"\n\n#include \"version_major.h\"\n\n#define LIBAVCODEC_VERSION_MINOR  37\n#define LIBAVCODEC_VERSION_MICRO 100\n\n#define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \\\n                                               LIBAVCODEC_VERSION_MINOR, \\\n                                               LIBAVCODEC_VERSION_MICRO)\n#define LIBAVCODEC_VERSION      AV_VERSION(LIBAVCODEC_VERSION_MAJOR,    \\\n                                           LIBAVCODEC_VERSION_MINOR,    \\\n                                           LIBAVCODEC_VERSION_MICRO)\n#define LIBAVCODEC_BUILD        LIBAVCODEC_VERSION_INT\n\n#define LIBAVCODEC_IDENT        \"Lavc\" AV_STRINGIFY(LIBAVCODEC_VERSION)\n\n#endif /* AVCODEC_VERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/version_major.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_VERSION_MAJOR_H\n#define AVCODEC_VERSION_MAJOR_H\n\n/**\n * @file\n * @ingroup libavc\n * Libavcodec version macros.\n */\n\n#define LIBAVCODEC_VERSION_MAJOR  59\n\n/**\n * FF_API_* defines may be placed below to indicate public API that will be\n * dropped at a future version bump. The defines themselves are not part of\n * the public API and may change, break or disappear at any time.\n *\n * @note, when bumping the major version it is recommended to manually\n * disable each FF_API_* in its own commit instead of disabling them all\n * at once through the bump. This improves the git bisect-ability of the change.\n */\n\n#define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_OPENH264_CABAC      (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_UNUSED_CODEC_CAPS   (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_DEBUG_MV          (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_GET_FRAME_CLASS     (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_AUTO_THREADS        (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_INIT_PACKET         (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_AVCTX_TIMEBASE    (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_FLAG_TRUNCATED      (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_SUB_TEXT_FORMAT     (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_IDCT_NONE           (LIBAVCODEC_VERSION_MAJOR < 60)\n#define FF_API_SVTAV1_OPTS         (LIBAVCODEC_VERSION_MAJOR < 60)\n\n#endif /* AVCODEC_VERSION_MAJOR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/videotoolbox.h",
    "content": "/*\n * Videotoolbox hardware acceleration\n *\n * copyright (c) 2012 Sebastien Zwickert\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_VIDEOTOOLBOX_H\n#define AVCODEC_VIDEOTOOLBOX_H\n\n/**\n * @file\n * @ingroup lavc_codec_hwaccel_videotoolbox\n * Public libavcodec Videotoolbox header.\n */\n\n#include <stdint.h>\n\n#define Picture QuickdrawPicture\n#include <VideoToolbox/VideoToolbox.h>\n#undef Picture\n\n#include \"libavcodec/avcodec.h\"\n\n/**\n * This struct holds all the information that needs to be passed\n * between the caller and libavcodec for initializing Videotoolbox decoding.\n * Its size is not a part of the public ABI, it must be allocated with\n * av_videotoolbox_alloc_context() and freed with av_free().\n */\ntypedef struct AVVideotoolboxContext {\n    /**\n     * Videotoolbox decompression session object.\n     * Created and freed the caller.\n     */\n    VTDecompressionSessionRef session;\n\n    /**\n     * The output callback that must be passed to the session.\n     * Set by av_videottoolbox_default_init()\n     */\n    VTDecompressionOutputCallback output_callback;\n\n    /**\n     * CVPixelBuffer Format Type that Videotoolbox will use for decoded frames.\n     * set by the caller. If this is set to 0, then no specific format is\n     * requested from the decoder, and its native format is output.\n     */\n    OSType cv_pix_fmt_type;\n\n    /**\n     * CoreMedia Format Description that Videotoolbox will use to create the decompression session.\n     * Set by the caller.\n     */\n    CMVideoFormatDescriptionRef cm_fmt_desc;\n\n    /**\n     * CoreMedia codec type that Videotoolbox will use to create the decompression session.\n     * Set by the caller.\n     */\n    int cm_codec_type;\n} AVVideotoolboxContext;\n\n/**\n * Allocate and initialize a Videotoolbox context.\n *\n * This function should be called from the get_format() callback when the caller\n * selects the AV_PIX_FMT_VIDETOOLBOX format. The caller must then create\n * the decoder object (using the output callback provided by libavcodec) that\n * will be used for Videotoolbox-accelerated decoding.\n *\n * When decoding with Videotoolbox is finished, the caller must destroy the decoder\n * object and free the Videotoolbox context using av_free().\n *\n * @return the newly allocated context or NULL on failure\n */\nAVVideotoolboxContext *av_videotoolbox_alloc_context(void);\n\n/**\n * This is a convenience function that creates and sets up the Videotoolbox context using\n * an internal implementation.\n *\n * @param avctx the corresponding codec context\n *\n * @return >= 0 on success, a negative AVERROR code on failure\n */\nint av_videotoolbox_default_init(AVCodecContext *avctx);\n\n/**\n * This is a convenience function that creates and sets up the Videotoolbox context using\n * an internal implementation.\n *\n * @param avctx the corresponding codec context\n * @param vtctx the Videotoolbox context to use\n *\n * @return >= 0 on success, a negative AVERROR code on failure\n */\nint av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx);\n\n/**\n * This function must be called to free the Videotoolbox context initialized with\n * av_videotoolbox_default_init().\n *\n * @param avctx the corresponding codec context\n */\nvoid av_videotoolbox_default_free(AVCodecContext *avctx);\n\n/**\n * @}\n */\n\n#endif /* AVCODEC_VIDEOTOOLBOX_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/vorbis_parser.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * A public API for Vorbis parsing\n *\n * Determines the duration for each packet.\n */\n\n#ifndef AVCODEC_VORBIS_PARSER_H\n#define AVCODEC_VORBIS_PARSER_H\n\n#include <stdint.h>\n\ntypedef struct AVVorbisParseContext AVVorbisParseContext;\n\n/**\n * Allocate and initialize the Vorbis parser using headers in the extradata.\n */\nAVVorbisParseContext *av_vorbis_parse_init(const uint8_t *extradata,\n                                           int extradata_size);\n\n/**\n * Free the parser and everything associated with it.\n */\nvoid av_vorbis_parse_free(AVVorbisParseContext **s);\n\n#define VORBIS_FLAG_HEADER  0x00000001\n#define VORBIS_FLAG_COMMENT 0x00000002\n#define VORBIS_FLAG_SETUP   0x00000004\n\n/**\n * Get the duration for a Vorbis packet.\n *\n * If @p flags is @c NULL,\n * special frames are considered invalid.\n *\n * @param s        Vorbis parser context\n * @param buf      buffer containing a Vorbis frame\n * @param buf_size size of the buffer\n * @param flags    flags for special frames\n */\nint av_vorbis_parse_frame_flags(AVVorbisParseContext *s, const uint8_t *buf,\n                                int buf_size, int *flags);\n\n/**\n * Get the duration for a Vorbis packet.\n *\n * @param s        Vorbis parser context\n * @param buf      buffer containing a Vorbis frame\n * @param buf_size size of the buffer\n */\nint av_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf,\n                          int buf_size);\n\nvoid av_vorbis_parse_reset(AVVorbisParseContext *s);\n\n#endif /* AVCODEC_VORBIS_PARSER_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavcodec/xvmc.h",
    "content": "/*\n * Copyright (C) 2003 Ivan Kalvachev\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVCODEC_XVMC_H\n#define AVCODEC_XVMC_H\n\n/**\n * @file\n * @ingroup lavc_codec_hwaccel_xvmc\n * Public libavcodec XvMC header.\n */\n\n#pragma message(\"XvMC is no longer supported; this header is deprecated and will be removed\")\n\n#include <X11/extensions/XvMC.h>\n\n#include \"libavutil/attributes.h\"\n#include \"avcodec.h\"\n\n/**\n * @defgroup lavc_codec_hwaccel_xvmc XvMC\n * @ingroup lavc_codec_hwaccel\n *\n * @{\n */\n\n#define AV_XVMC_ID                    0x1DC711C0  /**< special value to ensure that regular pixel routines haven't corrupted the struct\n                                                       the number is 1337 speak for the letters IDCT MCo (motion compensation) */\n\nstruct attribute_deprecated xvmc_pix_fmt {\n    /** The field contains the special constant value AV_XVMC_ID.\n        It is used as a test that the application correctly uses the API,\n        and that there is no corruption caused by pixel routines.\n        - application - set during initialization\n        - libavcodec  - unchanged\n    */\n    int             xvmc_id;\n\n    /** Pointer to the block array allocated by XvMCCreateBlocks().\n        The array has to be freed by XvMCDestroyBlocks().\n        Each group of 64 values represents one data block of differential\n        pixel information (in MoCo mode) or coefficients for IDCT.\n        - application - set the pointer during initialization\n        - libavcodec  - fills coefficients/pixel data into the array\n    */\n    short*          data_blocks;\n\n    /** Pointer to the macroblock description array allocated by\n        XvMCCreateMacroBlocks() and freed by XvMCDestroyMacroBlocks().\n        - application - set the pointer during initialization\n        - libavcodec  - fills description data into the array\n    */\n    XvMCMacroBlock* mv_blocks;\n\n    /** Number of macroblock descriptions that can be stored in the mv_blocks\n        array.\n        - application - set during initialization\n        - libavcodec  - unchanged\n    */\n    int             allocated_mv_blocks;\n\n    /** Number of blocks that can be stored at once in the data_blocks array.\n        - application - set during initialization\n        - libavcodec  - unchanged\n    */\n    int             allocated_data_blocks;\n\n    /** Indicate that the hardware would interpret data_blocks as IDCT\n        coefficients and perform IDCT on them.\n        - application - set during initialization\n        - libavcodec  - unchanged\n    */\n    int             idct;\n\n    /** In MoCo mode it indicates that intra macroblocks are assumed to be in\n        unsigned format; same as the XVMC_INTRA_UNSIGNED flag.\n        - application - set during initialization\n        - libavcodec  - unchanged\n    */\n    int             unsigned_intra;\n\n    /** Pointer to the surface allocated by XvMCCreateSurface().\n        It has to be freed by XvMCDestroySurface() on application exit.\n        It identifies the frame and its state on the video hardware.\n        - application - set during initialization\n        - libavcodec  - unchanged\n    */\n    XvMCSurface*    p_surface;\n\n/** Set by the decoder before calling ff_draw_horiz_band(),\n    needed by the XvMCRenderSurface function. */\n//@{\n    /** Pointer to the surface used as past reference\n        - application - unchanged\n        - libavcodec  - set\n    */\n    XvMCSurface*    p_past_surface;\n\n    /** Pointer to the surface used as future reference\n        - application - unchanged\n        - libavcodec  - set\n    */\n    XvMCSurface*    p_future_surface;\n\n    /** top/bottom field or frame\n        - application - unchanged\n        - libavcodec  - set\n    */\n    unsigned int    picture_structure;\n\n    /** XVMC_SECOND_FIELD - 1st or 2nd field in the sequence\n        - application - unchanged\n        - libavcodec  - set\n    */\n    unsigned int    flags;\n//}@\n\n    /** Number of macroblock descriptions in the mv_blocks array\n        that have already been passed to the hardware.\n        - application - zeroes it on get_buffer().\n                        A successful ff_draw_horiz_band() may increment it\n                        with filled_mb_block_num or zero both.\n        - libavcodec  - unchanged\n    */\n    int             start_mv_blocks_num;\n\n    /** Number of new macroblock descriptions in the mv_blocks array (after\n        start_mv_blocks_num) that are filled by libavcodec and have to be\n        passed to the hardware.\n        - application - zeroes it on get_buffer() or after successful\n                        ff_draw_horiz_band().\n        - libavcodec  - increment with one of each stored MB\n    */\n    int             filled_mv_blocks_num;\n\n    /** Number of the next free data block; one data block consists of\n        64 short values in the data_blocks array.\n        All blocks before this one have already been claimed by placing their\n        position into the corresponding block description structure field,\n        that are part of the mv_blocks array.\n        - application - zeroes it on get_buffer().\n                        A successful ff_draw_horiz_band() may zero it together\n                        with start_mb_blocks_num.\n        - libavcodec  - each decoded macroblock increases it by the number\n                        of coded blocks it contains.\n    */\n    int             next_free_data_block_num;\n};\n\n/**\n * @}\n */\n\n#endif /* AVCODEC_XVMC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavdevice/avdevice.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVDEVICE_AVDEVICE_H\n#define AVDEVICE_AVDEVICE_H\n\n#include \"version_major.h\"\n#ifndef HAVE_AV_CONFIG_H\n/* When included as part of the ffmpeg build, only include the major version\n * to avoid unnecessary rebuilds. When included externally, keep including\n * the full version information. */\n#include \"version.h\"\n#endif\n\n/**\n * @file\n * @ingroup lavd\n * Main libavdevice API header\n */\n\n/**\n * @defgroup lavd libavdevice\n * Special devices muxing/demuxing library.\n *\n * Libavdevice is a complementary library to @ref libavf \"libavformat\". It\n * provides various \"special\" platform-specific muxers and demuxers, e.g. for\n * grabbing devices, audio capture and playback etc. As a consequence, the\n * (de)muxers in libavdevice are of the AVFMT_NOFILE type (they use their own\n * I/O functions). The filename passed to avformat_open_input() often does not\n * refer to an actually existing file, but has some special device-specific\n * meaning - e.g. for xcbgrab it is the display name.\n *\n * To use libavdevice, simply call avdevice_register_all() to register all\n * compiled muxers and demuxers. They all use standard libavformat API.\n *\n * @{\n */\n\n#include \"libavutil/log.h\"\n#include \"libavutil/opt.h\"\n#include \"libavutil/dict.h\"\n#include \"libavformat/avformat.h\"\n\n/**\n * Return the LIBAVDEVICE_VERSION_INT constant.\n */\nunsigned avdevice_version(void);\n\n/**\n * Return the libavdevice build-time configuration.\n */\nconst char *avdevice_configuration(void);\n\n/**\n * Return the libavdevice license.\n */\nconst char *avdevice_license(void);\n\n/**\n * Initialize libavdevice and register all the input and output devices.\n */\nvoid avdevice_register_all(void);\n\n/**\n * Audio input devices iterator.\n *\n * If d is NULL, returns the first registered input audio/video device,\n * if d is non-NULL, returns the next registered input audio/video device after d\n * or NULL if d is the last one.\n */\nconst AVInputFormat *av_input_audio_device_next(const AVInputFormat  *d);\n\n/**\n * Video input devices iterator.\n *\n * If d is NULL, returns the first registered input audio/video device,\n * if d is non-NULL, returns the next registered input audio/video device after d\n * or NULL if d is the last one.\n */\nconst AVInputFormat *av_input_video_device_next(const AVInputFormat  *d);\n\n/**\n * Audio output devices iterator.\n *\n * If d is NULL, returns the first registered output audio/video device,\n * if d is non-NULL, returns the next registered output audio/video device after d\n * or NULL if d is the last one.\n */\nconst AVOutputFormat *av_output_audio_device_next(const AVOutputFormat *d);\n\n/**\n * Video output devices iterator.\n *\n * If d is NULL, returns the first registered output audio/video device,\n * if d is non-NULL, returns the next registered output audio/video device after d\n * or NULL if d is the last one.\n */\nconst AVOutputFormat *av_output_video_device_next(const AVOutputFormat *d);\n\ntypedef struct AVDeviceRect {\n    int x;      /**< x coordinate of top left corner */\n    int y;      /**< y coordinate of top left corner */\n    int width;  /**< width */\n    int height; /**< height */\n} AVDeviceRect;\n\n/**\n * Message types used by avdevice_app_to_dev_control_message().\n */\nenum AVAppToDevMessageType {\n    /**\n     * Dummy message.\n     */\n    AV_APP_TO_DEV_NONE = MKBETAG('N','O','N','E'),\n\n    /**\n     * Window size change message.\n     *\n     * Message is sent to the device every time the application changes the size\n     * of the window device renders to.\n     * Message should also be sent right after window is created.\n     *\n     * data: AVDeviceRect: new window size.\n     */\n    AV_APP_TO_DEV_WINDOW_SIZE = MKBETAG('G','E','O','M'),\n\n    /**\n     * Repaint request message.\n     *\n     * Message is sent to the device when window has to be repainted.\n     *\n     * data: AVDeviceRect: area required to be repainted.\n     *       NULL: whole area is required to be repainted.\n     */\n    AV_APP_TO_DEV_WINDOW_REPAINT = MKBETAG('R','E','P','A'),\n\n    /**\n     * Request pause/play.\n     *\n     * Application requests pause/unpause playback.\n     * Mostly usable with devices that have internal buffer.\n     * By default devices are not paused.\n     *\n     * data: NULL\n     */\n    AV_APP_TO_DEV_PAUSE        = MKBETAG('P', 'A', 'U', ' '),\n    AV_APP_TO_DEV_PLAY         = MKBETAG('P', 'L', 'A', 'Y'),\n    AV_APP_TO_DEV_TOGGLE_PAUSE = MKBETAG('P', 'A', 'U', 'T'),\n\n    /**\n     * Volume control message.\n     *\n     * Set volume level. It may be device-dependent if volume\n     * is changed per stream or system wide. Per stream volume\n     * change is expected when possible.\n     *\n     * data: double: new volume with range of 0.0 - 1.0.\n     */\n    AV_APP_TO_DEV_SET_VOLUME = MKBETAG('S', 'V', 'O', 'L'),\n\n    /**\n     * Mute control messages.\n     *\n     * Change mute state. It may be device-dependent if mute status\n     * is changed per stream or system wide. Per stream mute status\n     * change is expected when possible.\n     *\n     * data: NULL.\n     */\n    AV_APP_TO_DEV_MUTE        = MKBETAG(' ', 'M', 'U', 'T'),\n    AV_APP_TO_DEV_UNMUTE      = MKBETAG('U', 'M', 'U', 'T'),\n    AV_APP_TO_DEV_TOGGLE_MUTE = MKBETAG('T', 'M', 'U', 'T'),\n\n    /**\n     * Get volume/mute messages.\n     *\n     * Force the device to send AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED or\n     * AV_DEV_TO_APP_MUTE_STATE_CHANGED command respectively.\n     *\n     * data: NULL.\n     */\n    AV_APP_TO_DEV_GET_VOLUME = MKBETAG('G', 'V', 'O', 'L'),\n    AV_APP_TO_DEV_GET_MUTE   = MKBETAG('G', 'M', 'U', 'T'),\n};\n\n/**\n * Message types used by avdevice_dev_to_app_control_message().\n */\nenum AVDevToAppMessageType {\n    /**\n     * Dummy message.\n     */\n    AV_DEV_TO_APP_NONE = MKBETAG('N','O','N','E'),\n\n    /**\n     * Create window buffer message.\n     *\n     * Device requests to create a window buffer. Exact meaning is device-\n     * and application-dependent. Message is sent before rendering first\n     * frame and all one-shot initializations should be done here.\n     * Application is allowed to ignore preferred window buffer size.\n     *\n     * @note: Application is obligated to inform about window buffer size\n     *        with AV_APP_TO_DEV_WINDOW_SIZE message.\n     *\n     * data: AVDeviceRect: preferred size of the window buffer.\n     *       NULL: no preferred size of the window buffer.\n     */\n    AV_DEV_TO_APP_CREATE_WINDOW_BUFFER = MKBETAG('B','C','R','E'),\n\n    /**\n     * Prepare window buffer message.\n     *\n     * Device requests to prepare a window buffer for rendering.\n     * Exact meaning is device- and application-dependent.\n     * Message is sent before rendering of each frame.\n     *\n     * data: NULL.\n     */\n    AV_DEV_TO_APP_PREPARE_WINDOW_BUFFER = MKBETAG('B','P','R','E'),\n\n    /**\n     * Display window buffer message.\n     *\n     * Device requests to display a window buffer.\n     * Message is sent when new frame is ready to be displayed.\n     * Usually buffers need to be swapped in handler of this message.\n     *\n     * data: NULL.\n     */\n    AV_DEV_TO_APP_DISPLAY_WINDOW_BUFFER = MKBETAG('B','D','I','S'),\n\n    /**\n     * Destroy window buffer message.\n     *\n     * Device requests to destroy a window buffer.\n     * Message is sent when device is about to be destroyed and window\n     * buffer is not required anymore.\n     *\n     * data: NULL.\n     */\n    AV_DEV_TO_APP_DESTROY_WINDOW_BUFFER = MKBETAG('B','D','E','S'),\n\n    /**\n     * Buffer fullness status messages.\n     *\n     * Device signals buffer overflow/underflow.\n     *\n     * data: NULL.\n     */\n    AV_DEV_TO_APP_BUFFER_OVERFLOW = MKBETAG('B','O','F','L'),\n    AV_DEV_TO_APP_BUFFER_UNDERFLOW = MKBETAG('B','U','F','L'),\n\n    /**\n     * Buffer readable/writable.\n     *\n     * Device informs that buffer is readable/writable.\n     * When possible, device informs how many bytes can be read/write.\n     *\n     * @warning Device may not inform when number of bytes than can be read/write changes.\n     *\n     * data: int64_t: amount of bytes available to read/write.\n     *       NULL: amount of bytes available to read/write is not known.\n     */\n    AV_DEV_TO_APP_BUFFER_READABLE = MKBETAG('B','R','D',' '),\n    AV_DEV_TO_APP_BUFFER_WRITABLE = MKBETAG('B','W','R',' '),\n\n    /**\n     * Mute state change message.\n     *\n     * Device informs that mute state has changed.\n     *\n     * data: int: 0 for not muted state, non-zero for muted state.\n     */\n    AV_DEV_TO_APP_MUTE_STATE_CHANGED = MKBETAG('C','M','U','T'),\n\n    /**\n     * Volume level change message.\n     *\n     * Device informs that volume level has changed.\n     *\n     * data: double: new volume with range of 0.0 - 1.0.\n     */\n    AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED = MKBETAG('C','V','O','L'),\n};\n\n/**\n * Send control message from application to device.\n *\n * @param s         device context.\n * @param type      message type.\n * @param data      message data. Exact type depends on message type.\n * @param data_size size of message data.\n * @return >= 0 on success, negative on error.\n *         AVERROR(ENOSYS) when device doesn't implement handler of the message.\n */\nint avdevice_app_to_dev_control_message(struct AVFormatContext *s,\n                                        enum AVAppToDevMessageType type,\n                                        void *data, size_t data_size);\n\n/**\n * Send control message from device to application.\n *\n * @param s         device context.\n * @param type      message type.\n * @param data      message data. Can be NULL.\n * @param data_size size of message data.\n * @return >= 0 on success, negative on error.\n *         AVERROR(ENOSYS) when application doesn't implement handler of the message.\n */\nint avdevice_dev_to_app_control_message(struct AVFormatContext *s,\n                                        enum AVDevToAppMessageType type,\n                                        void *data, size_t data_size);\n\n#if FF_API_DEVICE_CAPABILITIES\n/**\n * Following API allows user to probe device capabilities (supported codecs,\n * pixel formats, sample formats, resolutions, channel counts, etc).\n * It is build on top op AVOption API.\n * Queried capabilities make it possible to set up converters of video or audio\n * parameters that fit to the device.\n *\n * List of capabilities that can be queried:\n *  - Capabilities valid for both audio and video devices:\n *    - codec:          supported audio/video codecs.\n *                      type: AV_OPT_TYPE_INT (AVCodecID value)\n *  - Capabilities valid for audio devices:\n *    - sample_format:  supported sample formats.\n *                      type: AV_OPT_TYPE_INT (AVSampleFormat value)\n *    - sample_rate:    supported sample rates.\n *                      type: AV_OPT_TYPE_INT\n *    - channels:       supported number of channels.\n *                      type: AV_OPT_TYPE_INT\n *    - channel_layout: supported channel layouts.\n *                      type: AV_OPT_TYPE_INT64\n *  - Capabilities valid for video devices:\n *    - pixel_format:   supported pixel formats.\n *                      type: AV_OPT_TYPE_INT (AVPixelFormat value)\n *    - window_size:    supported window sizes (describes size of the window size presented to the user).\n *                      type: AV_OPT_TYPE_IMAGE_SIZE\n *    - frame_size:     supported frame sizes (describes size of provided video frames).\n *                      type: AV_OPT_TYPE_IMAGE_SIZE\n *    - fps:            supported fps values\n *                      type: AV_OPT_TYPE_RATIONAL\n *\n * Value of the capability may be set by user using av_opt_set() function\n * and AVDeviceCapabilitiesQuery object. Following queries will\n * limit results to the values matching already set capabilities.\n * For example, setting a codec may impact number of formats or fps values\n * returned during next query. Setting invalid value may limit results to zero.\n *\n * Example of the usage basing on opengl output device:\n *\n * @code\n *  AVFormatContext *oc = NULL;\n *  AVDeviceCapabilitiesQuery *caps = NULL;\n *  AVOptionRanges *ranges;\n *  int ret;\n *\n *  if ((ret = avformat_alloc_output_context2(&oc, NULL, \"opengl\", NULL)) < 0)\n *      goto fail;\n *  if (avdevice_capabilities_create(&caps, oc, NULL) < 0)\n *      goto fail;\n *\n *  //query codecs\n *  if (av_opt_query_ranges(&ranges, caps, \"codec\", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)\n *      goto fail;\n *  //pick codec here and set it\n *  av_opt_set(caps, \"codec\", AV_CODEC_ID_RAWVIDEO, 0);\n *\n *  //query format\n *  if (av_opt_query_ranges(&ranges, caps, \"pixel_format\", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)\n *      goto fail;\n *  //pick format here and set it\n *  av_opt_set(caps, \"pixel_format\", AV_PIX_FMT_YUV420P, 0);\n *\n *  //query and set more capabilities\n *\n * fail:\n *  //clean up code\n *  avdevice_capabilities_free(&query, oc);\n *  avformat_free_context(oc);\n * @endcode\n */\n\n/**\n * Structure describes device capabilities.\n *\n * It is used by devices in conjunction with av_device_capabilities AVOption table\n * to implement capabilities probing API based on AVOption API. Should not be used directly.\n */\ntypedef struct AVDeviceCapabilitiesQuery {\n    const AVClass *av_class;\n    AVFormatContext *device_context;\n    enum AVCodecID codec;\n    enum AVSampleFormat sample_format;\n    enum AVPixelFormat pixel_format;\n    int sample_rate;\n    int channels;\n    int64_t channel_layout;\n    int window_width;\n    int window_height;\n    int frame_width;\n    int frame_height;\n    AVRational fps;\n} AVDeviceCapabilitiesQuery;\n\n/**\n * AVOption table used by devices to implement device capabilities API. Should not be used by a user.\n */\nattribute_deprecated\nextern const AVOption av_device_capabilities[];\n\n/**\n * Initialize capabilities probing API based on AVOption API.\n *\n * avdevice_capabilities_free() must be called when query capabilities API is\n * not used anymore.\n *\n * @param[out] caps      Device capabilities data. Pointer to a NULL pointer must be passed.\n * @param s              Context of the device.\n * @param device_options An AVDictionary filled with device-private options.\n *                       On return this parameter will be destroyed and replaced with a dict\n *                       containing options that were not found. May be NULL.\n *                       The same options must be passed later to avformat_write_header() for output\n *                       devices or avformat_open_input() for input devices, or at any other place\n *                       that affects device-private options.\n *\n * @return >= 0 on success, negative otherwise.\n */\nattribute_deprecated\nint avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,\n                                 AVDictionary **device_options);\n\n/**\n * Free resources created by avdevice_capabilities_create()\n *\n * @param caps Device capabilities data to be freed.\n * @param s    Context of the device.\n */\nattribute_deprecated\nvoid avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s);\n#endif\n\n/**\n * Structure describes basic parameters of the device.\n */\ntypedef struct AVDeviceInfo {\n    char *device_name;                   /**< device name, format depends on device */\n    char *device_description;            /**< human friendly name */\n    enum AVMediaType *media_types;       /**< array indicating what media types(s), if any, a device can provide. If null, cannot provide any */\n    int nb_media_types;                  /**< length of media_types array, 0 if device cannot provide any media types */\n} AVDeviceInfo;\n\n/**\n * List of devices.\n */\ntypedef struct AVDeviceInfoList {\n    AVDeviceInfo **devices;              /**< list of autodetected devices */\n    int nb_devices;                      /**< number of autodetected devices */\n    int default_device;                  /**< index of default device or -1 if no default */\n} AVDeviceInfoList;\n\n/**\n * List devices.\n *\n * Returns available device names and their parameters.\n *\n * @note: Some devices may accept system-dependent device names that cannot be\n *        autodetected. The list returned by this function cannot be assumed to\n *        be always completed.\n *\n * @param s                device context.\n * @param[out] device_list list of autodetected devices.\n * @return count of autodetected devices, negative on error.\n */\nint avdevice_list_devices(struct AVFormatContext *s, AVDeviceInfoList **device_list);\n\n/**\n * Convenient function to free result of avdevice_list_devices().\n *\n * @param devices device list to be freed.\n */\nvoid avdevice_free_list_devices(AVDeviceInfoList **device_list);\n\n/**\n * List devices.\n *\n * Returns available device names and their parameters.\n * These are convinient wrappers for avdevice_list_devices().\n * Device context is allocated and deallocated internally.\n *\n * @param device           device format. May be NULL if device name is set.\n * @param device_name      device name. May be NULL if device format is set.\n * @param device_options   An AVDictionary filled with device-private options. May be NULL.\n *                         The same options must be passed later to avformat_write_header() for output\n *                         devices or avformat_open_input() for input devices, or at any other place\n *                         that affects device-private options.\n * @param[out] device_list list of autodetected devices\n * @return count of autodetected devices, negative on error.\n * @note device argument takes precedence over device_name when both are set.\n */\nint avdevice_list_input_sources(const AVInputFormat *device, const char *device_name,\n                                AVDictionary *device_options, AVDeviceInfoList **device_list);\nint avdevice_list_output_sinks(const AVOutputFormat *device, const char *device_name,\n                               AVDictionary *device_options, AVDeviceInfoList **device_list);\n\n/**\n * @}\n */\n\n#endif /* AVDEVICE_AVDEVICE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavdevice/version.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVDEVICE_VERSION_H\n#define AVDEVICE_VERSION_H\n\n/**\n * @file\n * @ingroup lavd\n * Libavdevice version macros\n */\n\n#include \"libavutil/version.h\"\n\n#include \"version_major.h\"\n\n#define LIBAVDEVICE_VERSION_MINOR   7\n#define LIBAVDEVICE_VERSION_MICRO 100\n\n#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \\\n                                               LIBAVDEVICE_VERSION_MINOR, \\\n                                               LIBAVDEVICE_VERSION_MICRO)\n#define LIBAVDEVICE_VERSION     AV_VERSION(LIBAVDEVICE_VERSION_MAJOR, \\\n                                           LIBAVDEVICE_VERSION_MINOR, \\\n                                           LIBAVDEVICE_VERSION_MICRO)\n#define LIBAVDEVICE_BUILD       LIBAVDEVICE_VERSION_INT\n\n#define LIBAVDEVICE_IDENT       \"Lavd\" AV_STRINGIFY(LIBAVDEVICE_VERSION)\n\n#endif /* AVDEVICE_VERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavdevice/version_major.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVDEVICE_VERSION_MAJOR_H\n#define AVDEVICE_VERSION_MAJOR_H\n\n/**\n * @file\n * @ingroup lavd\n * Libavdevice version macros\n */\n\n#define LIBAVDEVICE_VERSION_MAJOR  59\n\n/**\n * FF_API_* defines may be placed below to indicate public API that will be\n * dropped at a future version bump. The defines themselves are not part of\n * the public API and may change, break or disappear at any time.\n */\n#define FF_API_DEVICE_CAPABILITIES (LIBAVDEVICE_VERSION_MAJOR < 60)\n\n#endif /* AVDEVICE_VERSION_MAJOR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavfilter/avfilter.h",
    "content": "/*\n * filter layer\n * Copyright (c) 2007 Bobby Bingham\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVFILTER_AVFILTER_H\n#define AVFILTER_AVFILTER_H\n\n/**\n * @file\n * @ingroup lavfi\n * Main libavfilter public API header\n */\n\n/**\n * @defgroup lavfi libavfilter\n * Graph-based frame editing library.\n *\n * @{\n */\n\n#include <stddef.h>\n\n#include \"libavutil/attributes.h\"\n#include \"libavutil/avutil.h\"\n#include \"libavutil/buffer.h\"\n#include \"libavutil/dict.h\"\n#include \"libavutil/frame.h\"\n#include \"libavutil/log.h\"\n#include \"libavutil/samplefmt.h\"\n#include \"libavutil/pixfmt.h\"\n#include \"libavutil/rational.h\"\n\n#include \"libavfilter/version_major.h\"\n#ifndef HAVE_AV_CONFIG_H\n/* When included as part of the ffmpeg build, only include the major version\n * to avoid unnecessary rebuilds. When included externally, keep including\n * the full version information. */\n#include \"libavfilter/version.h\"\n#endif\n\n/**\n * Return the LIBAVFILTER_VERSION_INT constant.\n */\nunsigned avfilter_version(void);\n\n/**\n * Return the libavfilter build-time configuration.\n */\nconst char *avfilter_configuration(void);\n\n/**\n * Return the libavfilter license.\n */\nconst char *avfilter_license(void);\n\ntypedef struct AVFilterContext AVFilterContext;\ntypedef struct AVFilterLink    AVFilterLink;\ntypedef struct AVFilterPad     AVFilterPad;\ntypedef struct AVFilterFormats AVFilterFormats;\ntypedef struct AVFilterChannelLayouts AVFilterChannelLayouts;\n\n#if FF_API_PAD_COUNT\n/**\n * Get the number of elements in an AVFilter's inputs or outputs array.\n *\n * @deprecated Use avfilter_filter_pad_count() instead.\n */\nattribute_deprecated\nint avfilter_pad_count(const AVFilterPad *pads);\n#endif\n\n/**\n * Get the name of an AVFilterPad.\n *\n * @param pads an array of AVFilterPads\n * @param pad_idx index of the pad in the array; it is the caller's\n *                responsibility to ensure the index is valid\n *\n * @return name of the pad_idx'th pad in pads\n */\nconst char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx);\n\n/**\n * Get the type of an AVFilterPad.\n *\n * @param pads an array of AVFilterPads\n * @param pad_idx index of the pad in the array; it is the caller's\n *                responsibility to ensure the index is valid\n *\n * @return type of the pad_idx'th pad in pads\n */\nenum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);\n\n/**\n * The number of the filter inputs is not determined just by AVFilter.inputs.\n * The filter might add additional inputs during initialization depending on the\n * options supplied to it.\n */\n#define AVFILTER_FLAG_DYNAMIC_INPUTS        (1 << 0)\n/**\n * The number of the filter outputs is not determined just by AVFilter.outputs.\n * The filter might add additional outputs during initialization depending on\n * the options supplied to it.\n */\n#define AVFILTER_FLAG_DYNAMIC_OUTPUTS       (1 << 1)\n/**\n * The filter supports multithreading by splitting frames into multiple parts\n * and processing them concurrently.\n */\n#define AVFILTER_FLAG_SLICE_THREADS         (1 << 2)\n/**\n * The filter is a \"metadata\" filter - it does not modify the frame data in any\n * way. It may only affect the metadata (i.e. those fields copied by\n * av_frame_copy_props()).\n *\n * More precisely, this means:\n * - video: the data of any frame output by the filter must be exactly equal to\n *   some frame that is received on one of its inputs. Furthermore, all frames\n *   produced on a given output must correspond to frames received on the same\n *   input and their order must be unchanged. Note that the filter may still\n *   drop or duplicate the frames.\n * - audio: the data produced by the filter on any of its outputs (viewed e.g.\n *   as an array of interleaved samples) must be exactly equal to the data\n *   received by the filter on one of its inputs.\n */\n#define AVFILTER_FLAG_METADATA_ONLY         (1 << 3)\n/**\n * Some filters support a generic \"enable\" expression option that can be used\n * to enable or disable a filter in the timeline. Filters supporting this\n * option have this flag set. When the enable expression is false, the default\n * no-op filter_frame() function is called in place of the filter_frame()\n * callback defined on each input pad, thus the frame is passed unchanged to\n * the next filters.\n */\n#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC  (1 << 16)\n/**\n * Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will\n * have its filter_frame() callback(s) called as usual even when the enable\n * expression is false. The filter will disable filtering within the\n * filter_frame() callback(s) itself, for example executing code depending on\n * the AVFilterContext->is_disabled value.\n */\n#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL (1 << 17)\n/**\n * Handy mask to test whether the filter supports or no the timeline feature\n * (internally or generically).\n */\n#define AVFILTER_FLAG_SUPPORT_TIMELINE (AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL)\n\n/**\n * Filter definition. This defines the pads a filter contains, and all the\n * callback functions used to interact with the filter.\n */\ntypedef struct AVFilter {\n    /**\n     * Filter name. Must be non-NULL and unique among filters.\n     */\n    const char *name;\n\n    /**\n     * A description of the filter. May be NULL.\n     *\n     * You should use the NULL_IF_CONFIG_SMALL() macro to define it.\n     */\n    const char *description;\n\n    /**\n     * List of static inputs.\n     *\n     * NULL if there are no (static) inputs. Instances of filters with\n     * AVFILTER_FLAG_DYNAMIC_INPUTS set may have more inputs than present in\n     * this list.\n     */\n    const AVFilterPad *inputs;\n\n    /**\n     * List of static outputs.\n     *\n     * NULL if there are no (static) outputs. Instances of filters with\n     * AVFILTER_FLAG_DYNAMIC_OUTPUTS set may have more outputs than present in\n     * this list.\n     */\n    const AVFilterPad *outputs;\n\n    /**\n     * A class for the private data, used to declare filter private AVOptions.\n     * This field is NULL for filters that do not declare any options.\n     *\n     * If this field is non-NULL, the first member of the filter private data\n     * must be a pointer to AVClass, which will be set by libavfilter generic\n     * code to this class.\n     */\n    const AVClass *priv_class;\n\n    /**\n     * A combination of AVFILTER_FLAG_*\n     */\n    int flags;\n\n    /*****************************************************************\n     * All fields below this line are not part of the public API. They\n     * may not be used outside of libavfilter and can be changed and\n     * removed at will.\n     * New public fields should be added right above.\n     *****************************************************************\n     */\n\n    /**\n     * The number of entries in the list of inputs.\n     */\n    uint8_t nb_inputs;\n\n    /**\n     * The number of entries in the list of outputs.\n     */\n    uint8_t nb_outputs;\n\n    /**\n     * This field determines the state of the formats union.\n     * It is an enum FilterFormatsState value.\n     */\n    uint8_t formats_state;\n\n    /**\n     * Filter pre-initialization function\n     *\n     * This callback will be called immediately after the filter context is\n     * allocated, to allow allocating and initing sub-objects.\n     *\n     * If this callback is not NULL, the uninit callback will be called on\n     * allocation failure.\n     *\n     * @return 0 on success,\n     *         AVERROR code on failure (but the code will be\n     *           dropped and treated as ENOMEM by the calling code)\n     */\n    int (*preinit)(AVFilterContext *ctx);\n\n    /**\n     * Filter initialization function.\n     *\n     * This callback will be called only once during the filter lifetime, after\n     * all the options have been set, but before links between filters are\n     * established and format negotiation is done.\n     *\n     * Basic filter initialization should be done here. Filters with dynamic\n     * inputs and/or outputs should create those inputs/outputs here based on\n     * provided options. No more changes to this filter's inputs/outputs can be\n     * done after this callback.\n     *\n     * This callback must not assume that the filter links exist or frame\n     * parameters are known.\n     *\n     * @ref AVFilter.uninit \"uninit\" is guaranteed to be called even if\n     * initialization fails, so this callback does not have to clean up on\n     * failure.\n     *\n     * @return 0 on success, a negative AVERROR on failure\n     */\n    int (*init)(AVFilterContext *ctx);\n\n    /**\n     * Should be set instead of @ref AVFilter.init \"init\" by the filters that\n     * want to pass a dictionary of AVOptions to nested contexts that are\n     * allocated during init.\n     *\n     * On return, the options dict should be freed and replaced with one that\n     * contains all the options which could not be processed by this filter (or\n     * with NULL if all the options were processed).\n     *\n     * Otherwise the semantics is the same as for @ref AVFilter.init \"init\".\n     */\n    int (*init_dict)(AVFilterContext *ctx, AVDictionary **options);\n\n    /**\n     * Filter uninitialization function.\n     *\n     * Called only once right before the filter is freed. Should deallocate any\n     * memory held by the filter, release any buffer references, etc. It does\n     * not need to deallocate the AVFilterContext.priv memory itself.\n     *\n     * This callback may be called even if @ref AVFilter.init \"init\" was not\n     * called or failed, so it must be prepared to handle such a situation.\n     */\n    void (*uninit)(AVFilterContext *ctx);\n\n    /**\n     * The state of the following union is determined by formats_state.\n     * See the documentation of enum FilterFormatsState in internal.h.\n     */\n    union {\n        /**\n         * Query formats supported by the filter on its inputs and outputs.\n         *\n         * This callback is called after the filter is initialized (so the inputs\n         * and outputs are fixed), shortly before the format negotiation. This\n         * callback may be called more than once.\n         *\n         * This callback must set AVFilterLink.outcfg.formats on every input link\n         * and AVFilterLink.incfg.formats on every output link to a list of\n         * pixel/sample formats that the filter supports on that link. For audio\n         * links, this filter must also set @ref AVFilterLink.incfg.samplerates\n         * \"in_samplerates\" / @ref AVFilterLink.outcfg.samplerates \"out_samplerates\"\n         * and @ref AVFilterLink.incfg.channel_layouts \"in_channel_layouts\" /\n         * @ref AVFilterLink.outcfg.channel_layouts \"out_channel_layouts\" analogously.\n         *\n         * This callback must never be NULL if the union is in this state.\n         *\n         * @return zero on success, a negative value corresponding to an\n         * AVERROR code otherwise\n         */\n        int (*query_func)(AVFilterContext *);\n        /**\n         * A pointer to an array of admissible pixel formats delimited\n         * by AV_PIX_FMT_NONE. The generic code will use this list\n         * to indicate that this filter supports each of these pixel formats,\n         * provided that all inputs and outputs use the same pixel format.\n         *\n         * This list must never be NULL if the union is in this state.\n         * The type of all inputs and outputs of filters using this must\n         * be AVMEDIA_TYPE_VIDEO.\n         */\n        const enum AVPixelFormat *pixels_list;\n        /**\n         * Analogous to pixels, but delimited by AV_SAMPLE_FMT_NONE\n         * and restricted to filters that only have AVMEDIA_TYPE_AUDIO\n         * inputs and outputs.\n         *\n         * In addition to that the generic code will mark all inputs\n         * and all outputs as supporting all sample rates and every\n         * channel count and channel layout, as long as all inputs\n         * and outputs use the same sample rate and channel count/layout.\n         */\n        const enum AVSampleFormat *samples_list;\n        /**\n         * Equivalent to { pix_fmt, AV_PIX_FMT_NONE } as pixels_list.\n         */\n        enum AVPixelFormat  pix_fmt;\n        /**\n         * Equivalent to { sample_fmt, AV_SAMPLE_FMT_NONE } as samples_list.\n         */\n        enum AVSampleFormat sample_fmt;\n    } formats;\n\n    int priv_size;      ///< size of private data to allocate for the filter\n\n    int flags_internal; ///< Additional flags for avfilter internal use only.\n\n    /**\n     * Make the filter instance process a command.\n     *\n     * @param cmd    the command to process, for handling simplicity all commands must be alphanumeric only\n     * @param arg    the argument for the command\n     * @param res    a buffer with size res_size where the filter(s) can return a response. This must not change when the command is not supported.\n     * @param flags  if AVFILTER_CMD_FLAG_FAST is set and the command would be\n     *               time consuming then a filter should treat it like an unsupported command\n     *\n     * @returns >=0 on success otherwise an error code.\n     *          AVERROR(ENOSYS) on unsupported commands\n     */\n    int (*process_command)(AVFilterContext *, const char *cmd, const char *arg, char *res, int res_len, int flags);\n\n    /**\n     * Filter activation function.\n     *\n     * Called when any processing is needed from the filter, instead of any\n     * filter_frame and request_frame on pads.\n     *\n     * The function must examine inlinks and outlinks and perform a single\n     * step of processing. If there is nothing to do, the function must do\n     * nothing and not return an error. If more steps are or may be\n     * possible, it must use ff_filter_set_ready() to schedule another\n     * activation.\n     */\n    int (*activate)(AVFilterContext *ctx);\n} AVFilter;\n\n/**\n * Get the number of elements in an AVFilter's inputs or outputs array.\n */\nunsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output);\n\n/**\n * Process multiple parts of the frame concurrently.\n */\n#define AVFILTER_THREAD_SLICE (1 << 0)\n\ntypedef struct AVFilterInternal AVFilterInternal;\n\n/** An instance of a filter */\nstruct AVFilterContext {\n    const AVClass *av_class;        ///< needed for av_log() and filters common options\n\n    const AVFilter *filter;         ///< the AVFilter of which this is an instance\n\n    char *name;                     ///< name of this filter instance\n\n    AVFilterPad   *input_pads;      ///< array of input pads\n    AVFilterLink **inputs;          ///< array of pointers to input links\n    unsigned    nb_inputs;          ///< number of input pads\n\n    AVFilterPad   *output_pads;     ///< array of output pads\n    AVFilterLink **outputs;         ///< array of pointers to output links\n    unsigned    nb_outputs;         ///< number of output pads\n\n    void *priv;                     ///< private data for use by the filter\n\n    struct AVFilterGraph *graph;    ///< filtergraph this filter belongs to\n\n    /**\n     * Type of multithreading being allowed/used. A combination of\n     * AVFILTER_THREAD_* flags.\n     *\n     * May be set by the caller before initializing the filter to forbid some\n     * or all kinds of multithreading for this filter. The default is allowing\n     * everything.\n     *\n     * When the filter is initialized, this field is combined using bit AND with\n     * AVFilterGraph.thread_type to get the final mask used for determining\n     * allowed threading types. I.e. a threading type needs to be set in both\n     * to be allowed.\n     *\n     * After the filter is initialized, libavfilter sets this field to the\n     * threading type that is actually used (0 for no multithreading).\n     */\n    int thread_type;\n\n    /**\n     * An opaque struct for libavfilter internal use.\n     */\n    AVFilterInternal *internal;\n\n    struct AVFilterCommand *command_queue;\n\n    char *enable_str;               ///< enable expression string\n    void *enable;                   ///< parsed expression (AVExpr*)\n    double *var_values;             ///< variable values for the enable expression\n    int is_disabled;                ///< the enabled state from the last expression evaluation\n\n    /**\n     * For filters which will create hardware frames, sets the device the\n     * filter should create them in.  All other filters will ignore this field:\n     * in particular, a filter which consumes or processes hardware frames will\n     * instead use the hw_frames_ctx field in AVFilterLink to carry the\n     * hardware context information.\n     */\n    AVBufferRef *hw_device_ctx;\n\n    /**\n     * Max number of threads allowed in this filter instance.\n     * If <= 0, its value is ignored.\n     * Overrides global number of threads set per filter graph.\n     */\n    int nb_threads;\n\n    /**\n     * Ready status of the filter.\n     * A non-0 value means that the filter needs activating;\n     * a higher value suggests a more urgent activation.\n     */\n    unsigned ready;\n\n    /**\n     * Sets the number of extra hardware frames which the filter will\n     * allocate on its output links for use in following filters or by\n     * the caller.\n     *\n     * Some hardware filters require all frames that they will use for\n     * output to be defined in advance before filtering starts.  For such\n     * filters, any hardware frame pools used for output must therefore be\n     * of fixed size.  The extra frames set here are on top of any number\n     * that the filter needs internally in order to operate normally.\n     *\n     * This field must be set before the graph containing this filter is\n     * configured.\n     */\n    int extra_hw_frames;\n};\n\n/**\n * Lists of formats / etc. supported by an end of a link.\n *\n * This structure is directly part of AVFilterLink, in two copies:\n * one for the source filter, one for the destination filter.\n\n * These lists are used for negotiating the format to actually be used,\n * which will be loaded into the format and channel_layout members of\n * AVFilterLink, when chosen.\n */\ntypedef struct AVFilterFormatsConfig {\n\n    /**\n     * List of supported formats (pixel or sample).\n     */\n    AVFilterFormats *formats;\n\n    /**\n     * Lists of supported sample rates, only for audio.\n     */\n    AVFilterFormats  *samplerates;\n\n    /**\n     * Lists of supported channel layouts, only for audio.\n     */\n    AVFilterChannelLayouts  *channel_layouts;\n\n} AVFilterFormatsConfig;\n\n/**\n * A link between two filters. This contains pointers to the source and\n * destination filters between which this link exists, and the indexes of\n * the pads involved. In addition, this link also contains the parameters\n * which have been negotiated and agreed upon between the filter, such as\n * image dimensions, format, etc.\n *\n * Applications must not normally access the link structure directly.\n * Use the buffersrc and buffersink API instead.\n * In the future, access to the header may be reserved for filters\n * implementation.\n */\nstruct AVFilterLink {\n    AVFilterContext *src;       ///< source filter\n    AVFilterPad *srcpad;        ///< output pad on the source filter\n\n    AVFilterContext *dst;       ///< dest filter\n    AVFilterPad *dstpad;        ///< input pad on the dest filter\n\n    enum AVMediaType type;      ///< filter media type\n\n    /* These parameters apply only to video */\n    int w;                      ///< agreed upon image width\n    int h;                      ///< agreed upon image height\n    AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio\n    /* These parameters apply only to audio */\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * channel layout of current buffer (see libavutil/channel_layout.h)\n     * @deprecated use ch_layout\n     */\n    attribute_deprecated\n    uint64_t channel_layout;\n#endif\n    int sample_rate;            ///< samples per second\n\n    int format;                 ///< agreed upon media format\n\n    /**\n     * Define the time base used by the PTS of the frames/samples\n     * which will pass through this link.\n     * During the configuration stage, each filter is supposed to\n     * change only the output timebase, while the timebase of the\n     * input link is assumed to be an unchangeable property.\n     */\n    AVRational time_base;\n\n    AVChannelLayout ch_layout;  ///< channel layout of current buffer (see libavutil/channel_layout.h)\n\n    /*****************************************************************\n     * All fields below this line are not part of the public API. They\n     * may not be used outside of libavfilter and can be changed and\n     * removed at will.\n     * New public fields should be added right above.\n     *****************************************************************\n     */\n\n    /**\n     * Lists of supported formats / etc. supported by the input filter.\n     */\n    AVFilterFormatsConfig incfg;\n\n    /**\n     * Lists of supported formats / etc. supported by the output filter.\n     */\n    AVFilterFormatsConfig outcfg;\n\n    /** stage of the initialization of the link properties (dimensions, etc) */\n    enum {\n        AVLINK_UNINIT = 0,      ///< not started\n        AVLINK_STARTINIT,       ///< started, but incomplete\n        AVLINK_INIT             ///< complete\n    } init_state;\n\n    /**\n     * Graph the filter belongs to.\n     */\n    struct AVFilterGraph *graph;\n\n    /**\n     * Current timestamp of the link, as defined by the most recent\n     * frame(s), in link time_base units.\n     */\n    int64_t current_pts;\n\n    /**\n     * Current timestamp of the link, as defined by the most recent\n     * frame(s), in AV_TIME_BASE units.\n     */\n    int64_t current_pts_us;\n\n    /**\n     * Index in the age array.\n     */\n    int age_index;\n\n    /**\n     * Frame rate of the stream on the link, or 1/0 if unknown or variable;\n     * if left to 0/0, will be automatically copied from the first input\n     * of the source filter if it exists.\n     *\n     * Sources should set it to the best estimation of the real frame rate.\n     * If the source frame rate is unknown or variable, set this to 1/0.\n     * Filters should update it if necessary depending on their function.\n     * Sinks can use it to set a default output frame rate.\n     * It is similar to the r_frame_rate field in AVStream.\n     */\n    AVRational frame_rate;\n\n    /**\n     * Minimum number of samples to filter at once. If filter_frame() is\n     * called with fewer samples, it will accumulate them in fifo.\n     * This field and the related ones must not be changed after filtering\n     * has started.\n     * If 0, all related fields are ignored.\n     */\n    int min_samples;\n\n    /**\n     * Maximum number of samples to filter at once. If filter_frame() is\n     * called with more samples, it will split them.\n     */\n    int max_samples;\n\n    /**\n     * Number of past frames sent through the link.\n     */\n    int64_t frame_count_in, frame_count_out;\n\n    /**\n     * Number of past samples sent through the link.\n     */\n    int64_t sample_count_in, sample_count_out;\n\n    /**\n     * A pointer to a FFFramePool struct.\n     */\n    void *frame_pool;\n\n    /**\n     * True if a frame is currently wanted on the output of this filter.\n     * Set when ff_request_frame() is called by the output,\n     * cleared when a frame is filtered.\n     */\n    int frame_wanted_out;\n\n    /**\n     * For hwaccel pixel formats, this should be a reference to the\n     * AVHWFramesContext describing the frames.\n     */\n    AVBufferRef *hw_frames_ctx;\n\n#ifndef FF_INTERNAL_FIELDS\n\n    /**\n     * Internal structure members.\n     * The fields below this limit are internal for libavfilter's use\n     * and must in no way be accessed by applications.\n     */\n    char reserved[0xF000];\n\n#else /* FF_INTERNAL_FIELDS */\n\n    /**\n     * Queue of frames waiting to be filtered.\n     */\n    FFFrameQueue fifo;\n\n    /**\n     * If set, the source filter can not generate a frame as is.\n     * The goal is to avoid repeatedly calling the request_frame() method on\n     * the same link.\n     */\n    int frame_blocked_in;\n\n    /**\n     * Link input status.\n     * If not zero, all attempts of filter_frame will fail with the\n     * corresponding code.\n     */\n    int status_in;\n\n    /**\n     * Timestamp of the input status change.\n     */\n    int64_t status_in_pts;\n\n    /**\n     * Link output status.\n     * If not zero, all attempts of request_frame will fail with the\n     * corresponding code.\n     */\n    int status_out;\n\n#endif /* FF_INTERNAL_FIELDS */\n\n};\n\n/**\n * Link two filters together.\n *\n * @param src    the source filter\n * @param srcpad index of the output pad on the source filter\n * @param dst    the destination filter\n * @param dstpad index of the input pad on the destination filter\n * @return       zero on success\n */\nint avfilter_link(AVFilterContext *src, unsigned srcpad,\n                  AVFilterContext *dst, unsigned dstpad);\n\n/**\n * Free the link in *link, and set its pointer to NULL.\n */\nvoid avfilter_link_free(AVFilterLink **link);\n\n/**\n * Negotiate the media format, dimensions, etc of all inputs to a filter.\n *\n * @param filter the filter to negotiate the properties for its inputs\n * @return       zero on successful negotiation\n */\nint avfilter_config_links(AVFilterContext *filter);\n\n#define AVFILTER_CMD_FLAG_ONE   1 ///< Stop once a filter understood the command (for target=all for example), fast filters are favored automatically\n#define AVFILTER_CMD_FLAG_FAST  2 ///< Only execute command when its fast (like a video out that supports contrast adjustment in hw)\n\n/**\n * Make the filter instance process a command.\n * It is recommended to use avfilter_graph_send_command().\n */\nint avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags);\n\n/**\n * Iterate over all registered filters.\n *\n * @param opaque a pointer where libavfilter will store the iteration state. Must\n *               point to NULL to start the iteration.\n *\n * @return the next registered filter or NULL when the iteration is\n *         finished\n */\nconst AVFilter *av_filter_iterate(void **opaque);\n\n/**\n * Get a filter definition matching the given name.\n *\n * @param name the filter name to find\n * @return     the filter definition, if any matching one is registered.\n *             NULL if none found.\n */\nconst AVFilter *avfilter_get_by_name(const char *name);\n\n\n/**\n * Initialize a filter with the supplied parameters.\n *\n * @param ctx  uninitialized filter context to initialize\n * @param args Options to initialize the filter with. This must be a\n *             ':'-separated list of options in the 'key=value' form.\n *             May be NULL if the options have been set directly using the\n *             AVOptions API or there are no options that need to be set.\n * @return 0 on success, a negative AVERROR on failure\n */\nint avfilter_init_str(AVFilterContext *ctx, const char *args);\n\n/**\n * Initialize a filter with the supplied dictionary of options.\n *\n * @param ctx     uninitialized filter context to initialize\n * @param options An AVDictionary filled with options for this filter. On\n *                return this parameter will be destroyed and replaced with\n *                a dict containing options that were not found. This dictionary\n *                must be freed by the caller.\n *                May be NULL, then this function is equivalent to\n *                avfilter_init_str() with the second parameter set to NULL.\n * @return 0 on success, a negative AVERROR on failure\n *\n * @note This function and avfilter_init_str() do essentially the same thing,\n * the difference is in manner in which the options are passed. It is up to the\n * calling code to choose whichever is more preferable. The two functions also\n * behave differently when some of the provided options are not declared as\n * supported by the filter. In such a case, avfilter_init_str() will fail, but\n * this function will leave those extra options in the options AVDictionary and\n * continue as usual.\n */\nint avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options);\n\n/**\n * Free a filter context. This will also remove the filter from its\n * filtergraph's list of filters.\n *\n * @param filter the filter to free\n */\nvoid avfilter_free(AVFilterContext *filter);\n\n/**\n * Insert a filter in the middle of an existing link.\n *\n * @param link the link into which the filter should be inserted\n * @param filt the filter to be inserted\n * @param filt_srcpad_idx the input pad on the filter to connect\n * @param filt_dstpad_idx the output pad on the filter to connect\n * @return     zero on success\n */\nint avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,\n                           unsigned filt_srcpad_idx, unsigned filt_dstpad_idx);\n\n/**\n * @return AVClass for AVFilterContext.\n *\n * @see av_opt_find().\n */\nconst AVClass *avfilter_get_class(void);\n\ntypedef struct AVFilterGraphInternal AVFilterGraphInternal;\n\n/**\n * A function pointer passed to the @ref AVFilterGraph.execute callback to be\n * executed multiple times, possibly in parallel.\n *\n * @param ctx the filter context the job belongs to\n * @param arg an opaque parameter passed through from @ref\n *            AVFilterGraph.execute\n * @param jobnr the index of the job being executed\n * @param nb_jobs the total number of jobs\n *\n * @return 0 on success, a negative AVERROR on error\n */\ntypedef int (avfilter_action_func)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);\n\n/**\n * A function executing multiple jobs, possibly in parallel.\n *\n * @param ctx the filter context to which the jobs belong\n * @param func the function to be called multiple times\n * @param arg the argument to be passed to func\n * @param ret a nb_jobs-sized array to be filled with return values from each\n *            invocation of func\n * @param nb_jobs the number of jobs to execute\n *\n * @return 0 on success, a negative AVERROR on error\n */\ntypedef int (avfilter_execute_func)(AVFilterContext *ctx, avfilter_action_func *func,\n                                    void *arg, int *ret, int nb_jobs);\n\ntypedef struct AVFilterGraph {\n    const AVClass *av_class;\n    AVFilterContext **filters;\n    unsigned nb_filters;\n\n    char *scale_sws_opts; ///< sws options to use for the auto-inserted scale filters\n\n    /**\n     * Type of multithreading allowed for filters in this graph. A combination\n     * of AVFILTER_THREAD_* flags.\n     *\n     * May be set by the caller at any point, the setting will apply to all\n     * filters initialized after that. The default is allowing everything.\n     *\n     * When a filter in this graph is initialized, this field is combined using\n     * bit AND with AVFilterContext.thread_type to get the final mask used for\n     * determining allowed threading types. I.e. a threading type needs to be\n     * set in both to be allowed.\n     */\n    int thread_type;\n\n    /**\n     * Maximum number of threads used by filters in this graph. May be set by\n     * the caller before adding any filters to the filtergraph. Zero (the\n     * default) means that the number of threads is determined automatically.\n     */\n    int nb_threads;\n\n    /**\n     * Opaque object for libavfilter internal use.\n     */\n    AVFilterGraphInternal *internal;\n\n    /**\n     * Opaque user data. May be set by the caller to an arbitrary value, e.g. to\n     * be used from callbacks like @ref AVFilterGraph.execute.\n     * Libavfilter will not touch this field in any way.\n     */\n    void *opaque;\n\n    /**\n     * This callback may be set by the caller immediately after allocating the\n     * graph and before adding any filters to it, to provide a custom\n     * multithreading implementation.\n     *\n     * If set, filters with slice threading capability will call this callback\n     * to execute multiple jobs in parallel.\n     *\n     * If this field is left unset, libavfilter will use its internal\n     * implementation, which may or may not be multithreaded depending on the\n     * platform and build options.\n     */\n    avfilter_execute_func *execute;\n\n    char *aresample_swr_opts; ///< swr options to use for the auto-inserted aresample filters, Access ONLY through AVOptions\n\n    /**\n     * Private fields\n     *\n     * The following fields are for internal use only.\n     * Their type, offset, number and semantic can change without notice.\n     */\n\n    AVFilterLink **sink_links;\n    int sink_links_count;\n\n    unsigned disable_auto_convert;\n} AVFilterGraph;\n\n/**\n * Allocate a filter graph.\n *\n * @return the allocated filter graph on success or NULL.\n */\nAVFilterGraph *avfilter_graph_alloc(void);\n\n/**\n * Create a new filter instance in a filter graph.\n *\n * @param graph graph in which the new filter will be used\n * @param filter the filter to create an instance of\n * @param name Name to give to the new instance (will be copied to\n *             AVFilterContext.name). This may be used by the caller to identify\n *             different filters, libavfilter itself assigns no semantics to\n *             this parameter. May be NULL.\n *\n * @return the context of the newly created filter instance (note that it is\n *         also retrievable directly through AVFilterGraph.filters or with\n *         avfilter_graph_get_filter()) on success or NULL on failure.\n */\nAVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph,\n                                             const AVFilter *filter,\n                                             const char *name);\n\n/**\n * Get a filter instance identified by instance name from graph.\n *\n * @param graph filter graph to search through.\n * @param name filter instance name (should be unique in the graph).\n * @return the pointer to the found filter instance or NULL if it\n * cannot be found.\n */\nAVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, const char *name);\n\n/**\n * Create and add a filter instance into an existing graph.\n * The filter instance is created from the filter filt and inited\n * with the parameter args. opaque is currently ignored.\n *\n * In case of success put in *filt_ctx the pointer to the created\n * filter instance, otherwise set *filt_ctx to NULL.\n *\n * @param name the instance name to give to the created filter instance\n * @param graph_ctx the filter graph\n * @return a negative AVERROR error code in case of failure, a non\n * negative value otherwise\n */\nint avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,\n                                 const char *name, const char *args, void *opaque,\n                                 AVFilterGraph *graph_ctx);\n\n/**\n * Enable or disable automatic format conversion inside the graph.\n *\n * Note that format conversion can still happen inside explicitly inserted\n * scale and aresample filters.\n *\n * @param flags  any of the AVFILTER_AUTO_CONVERT_* constants\n */\nvoid avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags);\n\nenum {\n    AVFILTER_AUTO_CONVERT_ALL  =  0, /**< all automatic conversions enabled */\n    AVFILTER_AUTO_CONVERT_NONE = -1, /**< all automatic conversions disabled */\n};\n\n/**\n * Check validity and configure all the links and formats in the graph.\n *\n * @param graphctx the filter graph\n * @param log_ctx context used for logging\n * @return >= 0 in case of success, a negative AVERROR code otherwise\n */\nint avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx);\n\n/**\n * Free a graph, destroy its links, and set *graph to NULL.\n * If *graph is NULL, do nothing.\n */\nvoid avfilter_graph_free(AVFilterGraph **graph);\n\n/**\n * A linked-list of the inputs/outputs of the filter chain.\n *\n * This is mainly useful for avfilter_graph_parse() / avfilter_graph_parse2(),\n * where it is used to communicate open (unlinked) inputs and outputs from and\n * to the caller.\n * This struct specifies, per each not connected pad contained in the graph, the\n * filter context and the pad index required for establishing a link.\n */\ntypedef struct AVFilterInOut {\n    /** unique name for this input/output in the list */\n    char *name;\n\n    /** filter context associated to this input/output */\n    AVFilterContext *filter_ctx;\n\n    /** index of the filt_ctx pad to use for linking */\n    int pad_idx;\n\n    /** next input/input in the list, NULL if this is the last */\n    struct AVFilterInOut *next;\n} AVFilterInOut;\n\n/**\n * Allocate a single AVFilterInOut entry.\n * Must be freed with avfilter_inout_free().\n * @return allocated AVFilterInOut on success, NULL on failure.\n */\nAVFilterInOut *avfilter_inout_alloc(void);\n\n/**\n * Free the supplied list of AVFilterInOut and set *inout to NULL.\n * If *inout is NULL, do nothing.\n */\nvoid avfilter_inout_free(AVFilterInOut **inout);\n\n/**\n * Add a graph described by a string to a graph.\n *\n * @note The caller must provide the lists of inputs and outputs,\n * which therefore must be known before calling the function.\n *\n * @note The inputs parameter describes inputs of the already existing\n * part of the graph; i.e. from the point of view of the newly created\n * part, they are outputs. Similarly the outputs parameter describes\n * outputs of the already existing filters, which are provided as\n * inputs to the parsed filters.\n *\n * @param graph   the filter graph where to link the parsed graph context\n * @param filters string to be parsed\n * @param inputs  linked list to the inputs of the graph\n * @param outputs linked list to the outputs of the graph\n * @return zero on success, a negative AVERROR code on error\n */\nint avfilter_graph_parse(AVFilterGraph *graph, const char *filters,\n                         AVFilterInOut *inputs, AVFilterInOut *outputs,\n                         void *log_ctx);\n\n/**\n * Add a graph described by a string to a graph.\n *\n * In the graph filters description, if the input label of the first\n * filter is not specified, \"in\" is assumed; if the output label of\n * the last filter is not specified, \"out\" is assumed.\n *\n * @param graph   the filter graph where to link the parsed graph context\n * @param filters string to be parsed\n * @param inputs  pointer to a linked list to the inputs of the graph, may be NULL.\n *                If non-NULL, *inputs is updated to contain the list of open inputs\n *                after the parsing, should be freed with avfilter_inout_free().\n * @param outputs pointer to a linked list to the outputs of the graph, may be NULL.\n *                If non-NULL, *outputs is updated to contain the list of open outputs\n *                after the parsing, should be freed with avfilter_inout_free().\n * @return non negative on success, a negative AVERROR code on error\n */\nint avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters,\n                             AVFilterInOut **inputs, AVFilterInOut **outputs,\n                             void *log_ctx);\n\n/**\n * Add a graph described by a string to a graph.\n *\n * @param[in]  graph   the filter graph where to link the parsed graph context\n * @param[in]  filters string to be parsed\n * @param[out] inputs  a linked list of all free (unlinked) inputs of the\n *                     parsed graph will be returned here. It is to be freed\n *                     by the caller using avfilter_inout_free().\n * @param[out] outputs a linked list of all free (unlinked) outputs of the\n *                     parsed graph will be returned here. It is to be freed by the\n *                     caller using avfilter_inout_free().\n * @return zero on success, a negative AVERROR code on error\n *\n * @note This function returns the inputs and outputs that are left\n * unlinked after parsing the graph and the caller then deals with\n * them.\n * @note This function makes no reference whatsoever to already\n * existing parts of the graph and the inputs parameter will on return\n * contain inputs of the newly parsed part of the graph.  Analogously\n * the outputs parameter will contain outputs of the newly created\n * filters.\n */\nint avfilter_graph_parse2(AVFilterGraph *graph, const char *filters,\n                          AVFilterInOut **inputs,\n                          AVFilterInOut **outputs);\n\n/**\n * Send a command to one or more filter instances.\n *\n * @param graph  the filter graph\n * @param target the filter(s) to which the command should be sent\n *               \"all\" sends to all filters\n *               otherwise it can be a filter or filter instance name\n *               which will send the command to all matching filters.\n * @param cmd    the command to send, for handling simplicity all commands must be alphanumeric only\n * @param arg    the argument for the command\n * @param res    a buffer with size res_size where the filter(s) can return a response.\n *\n * @returns >=0 on success otherwise an error code.\n *              AVERROR(ENOSYS) on unsupported commands\n */\nint avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags);\n\n/**\n * Queue a command for one or more filter instances.\n *\n * @param graph  the filter graph\n * @param target the filter(s) to which the command should be sent\n *               \"all\" sends to all filters\n *               otherwise it can be a filter or filter instance name\n *               which will send the command to all matching filters.\n * @param cmd    the command to sent, for handling simplicity all commands must be alphanumeric only\n * @param arg    the argument for the command\n * @param ts     time at which the command should be sent to the filter\n *\n * @note As this executes commands after this function returns, no return code\n *       from the filter is provided, also AVFILTER_CMD_FLAG_ONE is not supported.\n */\nint avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, int flags, double ts);\n\n\n/**\n * Dump a graph into a human-readable string representation.\n *\n * @param graph    the graph to dump\n * @param options  formatting options; currently ignored\n * @return  a string, or NULL in case of memory allocation failure;\n *          the string must be freed using av_free\n */\nchar *avfilter_graph_dump(AVFilterGraph *graph, const char *options);\n\n/**\n * Request a frame on the oldest sink link.\n *\n * If the request returns AVERROR_EOF, try the next.\n *\n * Note that this function is not meant to be the sole scheduling mechanism\n * of a filtergraph, only a convenience function to help drain a filtergraph\n * in a balanced way under normal circumstances.\n *\n * Also note that AVERROR_EOF does not mean that frames did not arrive on\n * some of the sinks during the process.\n * When there are multiple sink links, in case the requested link\n * returns an EOF, this may cause a filter to flush pending frames\n * which are sent to another sink link, although unrequested.\n *\n * @return  the return value of ff_request_frame(),\n *          or AVERROR_EOF if all links returned AVERROR_EOF\n */\nint avfilter_graph_request_oldest(AVFilterGraph *graph);\n\n/**\n * @}\n */\n\n#endif /* AVFILTER_AVFILTER_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavfilter/buffersink.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVFILTER_BUFFERSINK_H\n#define AVFILTER_BUFFERSINK_H\n\n/**\n * @file\n * @ingroup lavfi_buffersink\n * memory buffer sink API for audio and video\n */\n\n#include \"avfilter.h\"\n\n/**\n * @defgroup lavfi_buffersink Buffer sink API\n * @ingroup lavfi\n * @{\n *\n * The buffersink and abuffersink filters are there to connect filter graphs\n * to applications. They have a single input, connected to the graph, and no\n * output. Frames must be extracted using av_buffersink_get_frame() or\n * av_buffersink_get_samples().\n *\n * The format negotiated by the graph during configuration can be obtained\n * using the accessor functions:\n * - av_buffersink_get_time_base(),\n * - av_buffersink_get_format(),\n * - av_buffersink_get_frame_rate(),\n * - av_buffersink_get_w(),\n * - av_buffersink_get_h(),\n * - av_buffersink_get_sample_aspect_ratio(),\n * - av_buffersink_get_channels(),\n * - av_buffersink_get_ch_layout(),\n * - av_buffersink_get_sample_rate().\n *\n * The layout returned by av_buffersink_get_ch_layout() must de uninitialized\n * by the caller.\n *\n * The format can be constrained by setting options, using av_opt_set() and\n * related functions with the AV_OPT_SEARCH_CHILDREN flag.\n *  - pix_fmts (int list),\n *  - sample_fmts (int list),\n *  - sample_rates (int list),\n *  - ch_layouts (string),\n *  - channel_counts (int list),\n *  - all_channel_counts (bool).\n * Most of these options are of type binary, and should be set using\n * av_opt_set_int_list() or av_opt_set_bin(). If they are not set, all\n * corresponding formats are accepted.\n *\n * As a special case, if ch_layouts is not set, all valid channel layouts are\n * accepted except for UNSPEC layouts, unless all_channel_counts is set.\n */\n\n/**\n * Get a frame with filtered data from sink and put it in frame.\n *\n * @param ctx    pointer to a buffersink or abuffersink filter context.\n * @param frame  pointer to an allocated frame that will be filled with data.\n *               The data must be freed using av_frame_unref() / av_frame_free()\n * @param flags  a combination of AV_BUFFERSINK_FLAG_* flags\n *\n * @return  >= 0 in for success, a negative AVERROR code for failure.\n */\nint av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags);\n\n/**\n * Tell av_buffersink_get_buffer_ref() to read video/samples buffer\n * reference, but not remove it from the buffer. This is useful if you\n * need only to read a video/samples buffer, without to fetch it.\n */\n#define AV_BUFFERSINK_FLAG_PEEK 1\n\n/**\n * Tell av_buffersink_get_buffer_ref() not to request a frame from its input.\n * If a frame is already buffered, it is read (and removed from the buffer),\n * but if no frame is present, return AVERROR(EAGAIN).\n */\n#define AV_BUFFERSINK_FLAG_NO_REQUEST 2\n\n#if FF_API_BUFFERSINK_ALLOC\n/**\n * Deprecated and unused struct to use for initializing a buffersink context.\n */\ntypedef struct AVBufferSinkParams {\n    const enum AVPixelFormat *pixel_fmts; ///< list of allowed pixel formats, terminated by AV_PIX_FMT_NONE\n} AVBufferSinkParams;\n\n/**\n * Create an AVBufferSinkParams structure.\n *\n * Must be freed with av_free().\n */\nattribute_deprecated\nAVBufferSinkParams *av_buffersink_params_alloc(void);\n\n/**\n * Deprecated and unused struct to use for initializing an abuffersink context.\n */\ntypedef struct AVABufferSinkParams {\n    const enum AVSampleFormat *sample_fmts; ///< list of allowed sample formats, terminated by AV_SAMPLE_FMT_NONE\n    const int64_t *channel_layouts;         ///< list of allowed channel layouts, terminated by -1\n    const int *channel_counts;              ///< list of allowed channel counts, terminated by -1\n    int all_channel_counts;                 ///< if not 0, accept any channel count or layout\n    int *sample_rates;                      ///< list of allowed sample rates, terminated by -1\n} AVABufferSinkParams;\n\n/**\n * Create an AVABufferSinkParams structure.\n *\n * Must be freed with av_free().\n */\nattribute_deprecated\nAVABufferSinkParams *av_abuffersink_params_alloc(void);\n#endif\n\n/**\n * Set the frame size for an audio buffer sink.\n *\n * All calls to av_buffersink_get_buffer_ref will return a buffer with\n * exactly the specified number of samples, or AVERROR(EAGAIN) if there is\n * not enough. The last buffer at EOF will be padded with 0.\n */\nvoid av_buffersink_set_frame_size(AVFilterContext *ctx, unsigned frame_size);\n\n/**\n * @defgroup lavfi_buffersink_accessors Buffer sink accessors\n * Get the properties of the stream\n * @{\n */\n\nenum AVMediaType av_buffersink_get_type                (const AVFilterContext *ctx);\nAVRational       av_buffersink_get_time_base           (const AVFilterContext *ctx);\nint              av_buffersink_get_format              (const AVFilterContext *ctx);\n\nAVRational       av_buffersink_get_frame_rate          (const AVFilterContext *ctx);\nint              av_buffersink_get_w                   (const AVFilterContext *ctx);\nint              av_buffersink_get_h                   (const AVFilterContext *ctx);\nAVRational       av_buffersink_get_sample_aspect_ratio (const AVFilterContext *ctx);\n\nint              av_buffersink_get_channels            (const AVFilterContext *ctx);\n#if FF_API_OLD_CHANNEL_LAYOUT\nattribute_deprecated\nuint64_t         av_buffersink_get_channel_layout      (const AVFilterContext *ctx);\n#endif\nint              av_buffersink_get_ch_layout           (const AVFilterContext *ctx,\n                                                        AVChannelLayout *ch_layout);\nint              av_buffersink_get_sample_rate         (const AVFilterContext *ctx);\n\nAVBufferRef *    av_buffersink_get_hw_frames_ctx       (const AVFilterContext *ctx);\n\n/** @} */\n\n/**\n * Get a frame with filtered data from sink and put it in frame.\n *\n * @param ctx pointer to a context of a buffersink or abuffersink AVFilter.\n * @param frame pointer to an allocated frame that will be filled with data.\n *              The data must be freed using av_frame_unref() / av_frame_free()\n *\n * @return\n *         - >= 0 if a frame was successfully returned.\n *         - AVERROR(EAGAIN) if no frames are available at this point; more\n *           input frames must be added to the filtergraph to get more output.\n *         - AVERROR_EOF if there will be no more output frames on this sink.\n *         - A different negative AVERROR code in other failure cases.\n */\nint av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame);\n\n/**\n * Same as av_buffersink_get_frame(), but with the ability to specify the number\n * of samples read. This function is less efficient than\n * av_buffersink_get_frame(), because it copies the data around.\n *\n * @param ctx pointer to a context of the abuffersink AVFilter.\n * @param frame pointer to an allocated frame that will be filled with data.\n *              The data must be freed using av_frame_unref() / av_frame_free()\n *              frame will contain exactly nb_samples audio samples, except at\n *              the end of stream, when it can contain less than nb_samples.\n *\n * @return The return codes have the same meaning as for\n *         av_buffersink_get_frame().\n *\n * @warning do not mix this function with av_buffersink_get_frame(). Use only one or\n * the other with a single sink, not both.\n */\nint av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples);\n\n/**\n * @}\n */\n\n#endif /* AVFILTER_BUFFERSINK_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavfilter/buffersrc.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVFILTER_BUFFERSRC_H\n#define AVFILTER_BUFFERSRC_H\n\n/**\n * @file\n * @ingroup lavfi_buffersrc\n * Memory buffer source API.\n */\n\n#include \"avfilter.h\"\n\n/**\n * @defgroup lavfi_buffersrc Buffer source API\n * @ingroup lavfi\n * @{\n */\n\nenum {\n\n    /**\n     * Do not check for format changes.\n     */\n    AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1,\n\n    /**\n     * Immediately push the frame to the output.\n     */\n    AV_BUFFERSRC_FLAG_PUSH = 4,\n\n    /**\n     * Keep a reference to the frame.\n     * If the frame if reference-counted, create a new reference; otherwise\n     * copy the frame data.\n     */\n    AV_BUFFERSRC_FLAG_KEEP_REF = 8,\n\n};\n\n/**\n * Get the number of failed requests.\n *\n * A failed request is when the request_frame method is called while no\n * frame is present in the buffer.\n * The number is reset when a frame is added.\n */\nunsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src);\n\n/**\n * This structure contains the parameters describing the frames that will be\n * passed to this filter.\n *\n * It should be allocated with av_buffersrc_parameters_alloc() and freed with\n * av_free(). All the allocated fields in it remain owned by the caller.\n */\ntypedef struct AVBufferSrcParameters {\n    /**\n     * video: the pixel format, value corresponds to enum AVPixelFormat\n     * audio: the sample format, value corresponds to enum AVSampleFormat\n     */\n    int format;\n    /**\n     * The timebase to be used for the timestamps on the input frames.\n     */\n    AVRational time_base;\n\n    /**\n     * Video only, the display dimensions of the input frames.\n     */\n    int width, height;\n\n    /**\n     * Video only, the sample (pixel) aspect ratio.\n     */\n    AVRational sample_aspect_ratio;\n\n    /**\n     * Video only, the frame rate of the input video. This field must only be\n     * set to a non-zero value if input stream has a known constant framerate\n     * and should be left at its initial value if the framerate is variable or\n     * unknown.\n     */\n    AVRational frame_rate;\n\n    /**\n     * Video with a hwaccel pixel format only. This should be a reference to an\n     * AVHWFramesContext instance describing the input frames.\n     */\n    AVBufferRef *hw_frames_ctx;\n\n    /**\n     * Audio only, the audio sampling rate in samples per second.\n     */\n    int sample_rate;\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * Audio only, the audio channel layout\n     * @deprecated use ch_layout\n     */\n    attribute_deprecated\n    uint64_t channel_layout;\n#endif\n\n    /**\n     * Audio only, the audio channel layout\n     */\n    AVChannelLayout ch_layout;\n} AVBufferSrcParameters;\n\n/**\n * Allocate a new AVBufferSrcParameters instance. It should be freed by the\n * caller with av_free().\n */\nAVBufferSrcParameters *av_buffersrc_parameters_alloc(void);\n\n/**\n * Initialize the buffersrc or abuffersrc filter with the provided parameters.\n * This function may be called multiple times, the later calls override the\n * previous ones. Some of the parameters may also be set through AVOptions, then\n * whatever method is used last takes precedence.\n *\n * @param ctx an instance of the buffersrc or abuffersrc filter\n * @param param the stream parameters. The frames later passed to this filter\n *              must conform to those parameters. All the allocated fields in\n *              param remain owned by the caller, libavfilter will make internal\n *              copies or references when necessary.\n * @return 0 on success, a negative AVERROR code on failure.\n */\nint av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param);\n\n/**\n * Add a frame to the buffer source.\n *\n * @param ctx   an instance of the buffersrc filter\n * @param frame frame to be added. If the frame is reference counted, this\n * function will make a new reference to it. Otherwise the frame data will be\n * copied.\n *\n * @return 0 on success, a negative AVERROR on error\n *\n * This function is equivalent to av_buffersrc_add_frame_flags() with the\n * AV_BUFFERSRC_FLAG_KEEP_REF flag.\n */\nav_warn_unused_result\nint av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame);\n\n/**\n * Add a frame to the buffer source.\n *\n * @param ctx   an instance of the buffersrc filter\n * @param frame frame to be added. If the frame is reference counted, this\n * function will take ownership of the reference(s) and reset the frame.\n * Otherwise the frame data will be copied. If this function returns an error,\n * the input frame is not touched.\n *\n * @return 0 on success, a negative AVERROR on error.\n *\n * @note the difference between this function and av_buffersrc_write_frame() is\n * that av_buffersrc_write_frame() creates a new reference to the input frame,\n * while this function takes ownership of the reference passed to it.\n *\n * This function is equivalent to av_buffersrc_add_frame_flags() without the\n * AV_BUFFERSRC_FLAG_KEEP_REF flag.\n */\nav_warn_unused_result\nint av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame);\n\n/**\n * Add a frame to the buffer source.\n *\n * By default, if the frame is reference-counted, this function will take\n * ownership of the reference(s) and reset the frame. This can be controlled\n * using the flags.\n *\n * If this function returns an error, the input frame is not touched.\n *\n * @param buffer_src  pointer to a buffer source context\n * @param frame       a frame, or NULL to mark EOF\n * @param flags       a combination of AV_BUFFERSRC_FLAG_*\n * @return            >= 0 in case of success, a negative AVERROR code\n *                    in case of failure\n */\nav_warn_unused_result\nint av_buffersrc_add_frame_flags(AVFilterContext *buffer_src,\n                                 AVFrame *frame, int flags);\n\n/**\n * Close the buffer source after EOF.\n *\n * This is similar to passing NULL to av_buffersrc_add_frame_flags()\n * except it takes the timestamp of the EOF, i.e. the timestamp of the end\n * of the last frame.\n */\nint av_buffersrc_close(AVFilterContext *ctx, int64_t pts, unsigned flags);\n\n/**\n * @}\n */\n\n#endif /* AVFILTER_BUFFERSRC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavfilter/version.h",
    "content": "/*\n * Version macros.\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVFILTER_VERSION_H\n#define AVFILTER_VERSION_H\n\n/**\n * @file\n * @ingroup lavfi\n * Libavfilter version macros\n */\n\n#include \"libavutil/version.h\"\n\n#include \"version_major.h\"\n\n#define LIBAVFILTER_VERSION_MINOR  44\n#define LIBAVFILTER_VERSION_MICRO 100\n\n\n#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \\\n                                               LIBAVFILTER_VERSION_MINOR, \\\n                                               LIBAVFILTER_VERSION_MICRO)\n#define LIBAVFILTER_VERSION     AV_VERSION(LIBAVFILTER_VERSION_MAJOR,   \\\n                                           LIBAVFILTER_VERSION_MINOR,   \\\n                                           LIBAVFILTER_VERSION_MICRO)\n#define LIBAVFILTER_BUILD       LIBAVFILTER_VERSION_INT\n\n#define LIBAVFILTER_IDENT       \"Lavfi\" AV_STRINGIFY(LIBAVFILTER_VERSION)\n\n#endif /* AVFILTER_VERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavfilter/version_major.h",
    "content": "/*\n * Version macros.\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVFILTER_VERSION_MAJOR_H\n#define AVFILTER_VERSION_MAJOR_H\n\n/**\n * @file\n * @ingroup lavfi\n * Libavfilter version macros\n */\n\n#define LIBAVFILTER_VERSION_MAJOR   8\n\n/**\n * FF_API_* defines may be placed below to indicate public API that will be\n * dropped at a future version bump. The defines themselves are not part of\n * the public API and may change, break or disappear at any time.\n */\n\n#define FF_API_SWS_PARAM_OPTION             (LIBAVFILTER_VERSION_MAJOR < 9)\n#define FF_API_BUFFERSINK_ALLOC             (LIBAVFILTER_VERSION_MAJOR < 9)\n#define FF_API_PAD_COUNT                    (LIBAVFILTER_VERSION_MAJOR < 9)\n\n#endif /* AVFILTER_VERSION_MAJOR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavformat/avformat.h",
    "content": "/*\n * copyright (c) 2001 Fabrice Bellard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVFORMAT_AVFORMAT_H\n#define AVFORMAT_AVFORMAT_H\n\n/**\n * @file\n * @ingroup libavf\n * Main libavformat public API header\n */\n\n/**\n * @defgroup libavf libavformat\n * I/O and Muxing/Demuxing Library\n *\n * Libavformat (lavf) is a library for dealing with various media container\n * formats. Its main two purposes are demuxing - i.e. splitting a media file\n * into component streams, and the reverse process of muxing - writing supplied\n * data in a specified container format. It also has an @ref lavf_io\n * \"I/O module\" which supports a number of protocols for accessing the data (e.g.\n * file, tcp, http and others).\n * Unless you are absolutely sure you won't use libavformat's network\n * capabilities, you should also call avformat_network_init().\n *\n * A supported input format is described by an AVInputFormat struct, conversely\n * an output format is described by AVOutputFormat. You can iterate over all\n * input/output formats using the  av_demuxer_iterate / av_muxer_iterate() functions.\n * The protocols layer is not part of the public API, so you can only get the names\n * of supported protocols with the avio_enum_protocols() function.\n *\n * Main lavf structure used for both muxing and demuxing is AVFormatContext,\n * which exports all information about the file being read or written. As with\n * most Libavformat structures, its size is not part of public ABI, so it cannot be\n * allocated on stack or directly with av_malloc(). To create an\n * AVFormatContext, use avformat_alloc_context() (some functions, like\n * avformat_open_input() might do that for you).\n *\n * Most importantly an AVFormatContext contains:\n * @li the @ref AVFormatContext.iformat \"input\" or @ref AVFormatContext.oformat\n * \"output\" format. It is either autodetected or set by user for input;\n * always set by user for output.\n * @li an @ref AVFormatContext.streams \"array\" of AVStreams, which describe all\n * elementary streams stored in the file. AVStreams are typically referred to\n * using their index in this array.\n * @li an @ref AVFormatContext.pb \"I/O context\". It is either opened by lavf or\n * set by user for input, always set by user for output (unless you are dealing\n * with an AVFMT_NOFILE format).\n *\n * @section lavf_options Passing options to (de)muxers\n * It is possible to configure lavf muxers and demuxers using the @ref avoptions\n * mechanism. Generic (format-independent) libavformat options are provided by\n * AVFormatContext, they can be examined from a user program by calling\n * av_opt_next() / av_opt_find() on an allocated AVFormatContext (or its AVClass\n * from avformat_get_class()). Private (format-specific) options are provided by\n * AVFormatContext.priv_data if and only if AVInputFormat.priv_class /\n * AVOutputFormat.priv_class of the corresponding format struct is non-NULL.\n * Further options may be provided by the @ref AVFormatContext.pb \"I/O context\",\n * if its AVClass is non-NULL, and the protocols layer. See the discussion on\n * nesting in @ref avoptions documentation to learn how to access those.\n *\n * @section urls\n * URL strings in libavformat are made of a scheme/protocol, a ':', and a\n * scheme specific string. URLs without a scheme and ':' used for local files\n * are supported but deprecated. \"file:\" should be used for local files.\n *\n * It is important that the scheme string is not taken from untrusted\n * sources without checks.\n *\n * Note that some schemes/protocols are quite powerful, allowing access to\n * both local and remote files, parts of them, concatenations of them, local\n * audio and video devices and so on.\n *\n * @{\n *\n * @defgroup lavf_decoding Demuxing\n * @{\n * Demuxers read a media file and split it into chunks of data (@em packets). A\n * @ref AVPacket \"packet\" contains one or more encoded frames which belongs to a\n * single elementary stream. In the lavf API this process is represented by the\n * avformat_open_input() function for opening a file, av_read_frame() for\n * reading a single packet and finally avformat_close_input(), which does the\n * cleanup.\n *\n * @section lavf_decoding_open Opening a media file\n * The minimum information required to open a file is its URL, which\n * is passed to avformat_open_input(), as in the following code:\n * @code\n * const char    *url = \"file:in.mp3\";\n * AVFormatContext *s = NULL;\n * int ret = avformat_open_input(&s, url, NULL, NULL);\n * if (ret < 0)\n *     abort();\n * @endcode\n * The above code attempts to allocate an AVFormatContext, open the\n * specified file (autodetecting the format) and read the header, exporting the\n * information stored there into s. Some formats do not have a header or do not\n * store enough information there, so it is recommended that you call the\n * avformat_find_stream_info() function which tries to read and decode a few\n * frames to find missing information.\n *\n * In some cases you might want to preallocate an AVFormatContext yourself with\n * avformat_alloc_context() and do some tweaking on it before passing it to\n * avformat_open_input(). One such case is when you want to use custom functions\n * for reading input data instead of lavf internal I/O layer.\n * To do that, create your own AVIOContext with avio_alloc_context(), passing\n * your reading callbacks to it. Then set the @em pb field of your\n * AVFormatContext to newly created AVIOContext.\n *\n * Since the format of the opened file is in general not known until after\n * avformat_open_input() has returned, it is not possible to set demuxer private\n * options on a preallocated context. Instead, the options should be passed to\n * avformat_open_input() wrapped in an AVDictionary:\n * @code\n * AVDictionary *options = NULL;\n * av_dict_set(&options, \"video_size\", \"640x480\", 0);\n * av_dict_set(&options, \"pixel_format\", \"rgb24\", 0);\n *\n * if (avformat_open_input(&s, url, NULL, &options) < 0)\n *     abort();\n * av_dict_free(&options);\n * @endcode\n * This code passes the private options 'video_size' and 'pixel_format' to the\n * demuxer. They would be necessary for e.g. the rawvideo demuxer, since it\n * cannot know how to interpret raw video data otherwise. If the format turns\n * out to be something different than raw video, those options will not be\n * recognized by the demuxer and therefore will not be applied. Such unrecognized\n * options are then returned in the options dictionary (recognized options are\n * consumed). The calling program can handle such unrecognized options as it\n * wishes, e.g.\n * @code\n * AVDictionaryEntry *e;\n * if (e = av_dict_get(options, \"\", NULL, AV_DICT_IGNORE_SUFFIX)) {\n *     fprintf(stderr, \"Option %s not recognized by the demuxer.\\n\", e->key);\n *     abort();\n * }\n * @endcode\n *\n * After you have finished reading the file, you must close it with\n * avformat_close_input(). It will free everything associated with the file.\n *\n * @section lavf_decoding_read Reading from an opened file\n * Reading data from an opened AVFormatContext is done by repeatedly calling\n * av_read_frame() on it. Each call, if successful, will return an AVPacket\n * containing encoded data for one AVStream, identified by\n * AVPacket.stream_index. This packet may be passed straight into the libavcodec\n * decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the\n * caller wishes to decode the data.\n *\n * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be\n * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for\n * pts/dts, 0 for duration) if the stream does not provide them. The timing\n * information will be in AVStream.time_base units, i.e. it has to be\n * multiplied by the timebase to convert them to seconds.\n *\n * A packet returned by av_read_frame() is always reference-counted,\n * i.e. AVPacket.buf is set and the user may keep it indefinitely.\n * The packet must be freed with av_packet_unref() when it is no\n * longer needed.\n *\n * @section lavf_decoding_seek Seeking\n * @}\n *\n * @defgroup lavf_encoding Muxing\n * @{\n * Muxers take encoded data in the form of @ref AVPacket \"AVPackets\" and write\n * it into files or other output bytestreams in the specified container format.\n *\n * The main API functions for muxing are avformat_write_header() for writing the\n * file header, av_write_frame() / av_interleaved_write_frame() for writing the\n * packets and av_write_trailer() for finalizing the file.\n *\n * At the beginning of the muxing process, the caller must first call\n * avformat_alloc_context() to create a muxing context. The caller then sets up\n * the muxer by filling the various fields in this context:\n *\n * - The @ref AVFormatContext.oformat \"oformat\" field must be set to select the\n *   muxer that will be used.\n * - Unless the format is of the AVFMT_NOFILE type, the @ref AVFormatContext.pb\n *   \"pb\" field must be set to an opened IO context, either returned from\n *   avio_open2() or a custom one.\n * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must\n *   be created with the avformat_new_stream() function. The caller should fill\n *   the @ref AVStream.codecpar \"stream codec parameters\" information, such as the\n *   codec @ref AVCodecParameters.codec_type \"type\", @ref AVCodecParameters.codec_id\n *   \"id\" and other parameters (e.g. width / height, the pixel or sample format,\n *   etc.) as known. The @ref AVStream.time_base \"stream timebase\" should\n *   be set to the timebase that the caller desires to use for this stream (note\n *   that the timebase actually used by the muxer can be different, as will be\n *   described later).\n * - It is advised to manually initialize only the relevant fields in\n *   AVCodecParameters, rather than using @ref avcodec_parameters_copy() during\n *   remuxing: there is no guarantee that the codec context values remain valid\n *   for both input and output format contexts.\n * - The caller may fill in additional information, such as @ref\n *   AVFormatContext.metadata \"global\" or @ref AVStream.metadata \"per-stream\"\n *   metadata, @ref AVFormatContext.chapters \"chapters\", @ref\n *   AVFormatContext.programs \"programs\", etc. as described in the\n *   AVFormatContext documentation. Whether such information will actually be\n *   stored in the output depends on what the container format and the muxer\n *   support.\n *\n * When the muxing context is fully set up, the caller must call\n * avformat_write_header() to initialize the muxer internals and write the file\n * header. Whether anything actually is written to the IO context at this step\n * depends on the muxer, but this function must always be called. Any muxer\n * private options must be passed in the options parameter to this function.\n *\n * The data is then sent to the muxer by repeatedly calling av_write_frame() or\n * av_interleaved_write_frame() (consult those functions' documentation for\n * discussion on the difference between them; only one of them may be used with\n * a single muxing context, they should not be mixed). Do note that the timing\n * information on the packets sent to the muxer must be in the corresponding\n * AVStream's timebase. That timebase is set by the muxer (in the\n * avformat_write_header() step) and may be different from the timebase\n * requested by the caller.\n *\n * Once all the data has been written, the caller must call av_write_trailer()\n * to flush any buffered packets and finalize the output file, then close the IO\n * context (if any) and finally free the muxing context with\n * avformat_free_context().\n * @}\n *\n * @defgroup lavf_io I/O Read/Write\n * @{\n * @section lavf_io_dirlist Directory listing\n * The directory listing API makes it possible to list files on remote servers.\n *\n * Some of possible use cases:\n * - an \"open file\" dialog to choose files from a remote location,\n * - a recursive media finder providing a player with an ability to play all\n * files from a given directory.\n *\n * @subsection lavf_io_dirlist_open Opening a directory\n * At first, a directory needs to be opened by calling avio_open_dir()\n * supplied with a URL and, optionally, ::AVDictionary containing\n * protocol-specific parameters. The function returns zero or positive\n * integer and allocates AVIODirContext on success.\n *\n * @code\n * AVIODirContext *ctx = NULL;\n * if (avio_open_dir(&ctx, \"smb://example.com/some_dir\", NULL) < 0) {\n *     fprintf(stderr, \"Cannot open directory.\\n\");\n *     abort();\n * }\n * @endcode\n *\n * This code tries to open a sample directory using smb protocol without\n * any additional parameters.\n *\n * @subsection lavf_io_dirlist_read Reading entries\n * Each directory's entry (i.e. file, another directory, anything else\n * within ::AVIODirEntryType) is represented by AVIODirEntry.\n * Reading consecutive entries from an opened AVIODirContext is done by\n * repeatedly calling avio_read_dir() on it. Each call returns zero or\n * positive integer if successful. Reading can be stopped right after the\n * NULL entry has been read -- it means there are no entries left to be\n * read. The following code reads all entries from a directory associated\n * with ctx and prints their names to standard output.\n * @code\n * AVIODirEntry *entry = NULL;\n * for (;;) {\n *     if (avio_read_dir(ctx, &entry) < 0) {\n *         fprintf(stderr, \"Cannot list directory.\\n\");\n *         abort();\n *     }\n *     if (!entry)\n *         break;\n *     printf(\"%s\\n\", entry->name);\n *     avio_free_directory_entry(&entry);\n * }\n * @endcode\n * @}\n *\n * @defgroup lavf_codec Demuxers\n * @{\n * @defgroup lavf_codec_native Native Demuxers\n * @{\n * @}\n * @defgroup lavf_codec_wrappers External library wrappers\n * @{\n * @}\n * @}\n * @defgroup lavf_protos I/O Protocols\n * @{\n * @}\n * @defgroup lavf_internal Internal\n * @{\n * @}\n * @}\n */\n\n#include <time.h>\n#include <stdio.h>  /* FILE */\n\n#include \"libavcodec/codec.h\"\n#include \"libavcodec/codec_par.h\"\n#include \"libavcodec/defs.h\"\n#include \"libavcodec/packet.h\"\n\n#include \"libavutil/dict.h\"\n#include \"libavutil/log.h\"\n\n#include \"avio.h\"\n#include \"libavformat/version_major.h\"\n#ifndef HAVE_AV_CONFIG_H\n/* When included as part of the ffmpeg build, only include the major version\n * to avoid unnecessary rebuilds. When included externally, keep including\n * the full version information. */\n#include \"libavformat/version.h\"\n#endif\n\nstruct AVFormatContext;\nstruct AVStream;\n\nstruct AVDeviceInfoList;\nstruct AVDeviceCapabilitiesQuery;\n\n/**\n * @defgroup metadata_api Public Metadata API\n * @{\n * @ingroup libavf\n * The metadata API allows libavformat to export metadata tags to a client\n * application when demuxing. Conversely it allows a client application to\n * set metadata when muxing.\n *\n * Metadata is exported or set as pairs of key/value strings in the 'metadata'\n * fields of the AVFormatContext, AVStream, AVChapter and AVProgram structs\n * using the @ref lavu_dict \"AVDictionary\" API. Like all strings in FFmpeg,\n * metadata is assumed to be UTF-8 encoded Unicode. Note that metadata\n * exported by demuxers isn't checked to be valid UTF-8 in most cases.\n *\n * Important concepts to keep in mind:\n * -  Keys are unique; there can never be 2 tags with the same key. This is\n *    also meant semantically, i.e., a demuxer should not knowingly produce\n *    several keys that are literally different but semantically identical.\n *    E.g., key=Author5, key=Author6. In this example, all authors must be\n *    placed in the same tag.\n * -  Metadata is flat, not hierarchical; there are no subtags. If you\n *    want to store, e.g., the email address of the child of producer Alice\n *    and actor Bob, that could have key=alice_and_bobs_childs_email_address.\n * -  Several modifiers can be applied to the tag name. This is done by\n *    appending a dash character ('-') and the modifier name in the order\n *    they appear in the list below -- e.g. foo-eng-sort, not foo-sort-eng.\n *    -  language -- a tag whose value is localized for a particular language\n *       is appended with the ISO 639-2/B 3-letter language code.\n *       For example: Author-ger=Michael, Author-eng=Mike\n *       The original/default language is in the unqualified \"Author\" tag.\n *       A demuxer should set a default if it sets any translated tag.\n *    -  sorting  -- a modified version of a tag that should be used for\n *       sorting will have '-sort' appended. E.g. artist=\"The Beatles\",\n *       artist-sort=\"Beatles, The\".\n * - Some protocols and demuxers support metadata updates. After a successful\n *   call to av_read_frame(), AVFormatContext.event_flags or AVStream.event_flags\n *   will be updated to indicate if metadata changed. In order to detect metadata\n *   changes on a stream, you need to loop through all streams in the AVFormatContext\n *   and check their individual event_flags.\n *\n * -  Demuxers attempt to export metadata in a generic format, however tags\n *    with no generic equivalents are left as they are stored in the container.\n *    Follows a list of generic tag names:\n *\n @verbatim\n album        -- name of the set this work belongs to\n album_artist -- main creator of the set/album, if different from artist.\n                 e.g. \"Various Artists\" for compilation albums.\n artist       -- main creator of the work\n comment      -- any additional description of the file.\n composer     -- who composed the work, if different from artist.\n copyright    -- name of copyright holder.\n creation_time-- date when the file was created, preferably in ISO 8601.\n date         -- date when the work was created, preferably in ISO 8601.\n disc         -- number of a subset, e.g. disc in a multi-disc collection.\n encoder      -- name/settings of the software/hardware that produced the file.\n encoded_by   -- person/group who created the file.\n filename     -- original name of the file.\n genre        -- <self-evident>.\n language     -- main language in which the work is performed, preferably\n                 in ISO 639-2 format. Multiple languages can be specified by\n                 separating them with commas.\n performer    -- artist who performed the work, if different from artist.\n                 E.g for \"Also sprach Zarathustra\", artist would be \"Richard\n                 Strauss\" and performer \"London Philharmonic Orchestra\".\n publisher    -- name of the label/publisher.\n service_name     -- name of the service in broadcasting (channel name).\n service_provider -- name of the service provider in broadcasting.\n title        -- name of the work.\n track        -- number of this work in the set, can be in form current/total.\n variant_bitrate -- the total bitrate of the bitrate variant that the current stream is part of\n @endverbatim\n *\n * Look in the examples section for an application example how to use the Metadata API.\n *\n * @}\n */\n\n/* packet functions */\n\n\n/**\n * Allocate and read the payload of a packet and initialize its\n * fields with default values.\n *\n * @param s    associated IO context\n * @param pkt packet\n * @param size desired payload size\n * @return >0 (read size) if OK, AVERROR_xxx otherwise\n */\nint av_get_packet(AVIOContext *s, AVPacket *pkt, int size);\n\n\n/**\n * Read data and append it to the current content of the AVPacket.\n * If pkt->size is 0 this is identical to av_get_packet.\n * Note that this uses av_grow_packet and thus involves a realloc\n * which is inefficient. Thus this function should only be used\n * when there is no reasonable way to know (an upper bound of)\n * the final size.\n *\n * @param s    associated IO context\n * @param pkt packet\n * @param size amount of data to read\n * @return >0 (read size) if OK, AVERROR_xxx otherwise, previous data\n *         will not be lost even if an error occurs.\n */\nint av_append_packet(AVIOContext *s, AVPacket *pkt, int size);\n\n/*************************************************/\n/* input/output formats */\n\nstruct AVCodecTag;\n\n/**\n * This structure contains the data a format has to probe a file.\n */\ntypedef struct AVProbeData {\n    const char *filename;\n    unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */\n    int buf_size;       /**< Size of buf except extra allocated bytes */\n    const char *mime_type; /**< mime_type, when known. */\n} AVProbeData;\n\n#define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4)\n#define AVPROBE_SCORE_STREAM_RETRY (AVPROBE_SCORE_MAX/4-1)\n\n#define AVPROBE_SCORE_EXTENSION  50 ///< score for file extension\n#define AVPROBE_SCORE_MIME       75 ///< score for file mime type\n#define AVPROBE_SCORE_MAX       100 ///< maximum score\n\n#define AVPROBE_PADDING_SIZE 32             ///< extra allocated bytes at the end of the probe buffer\n\n/// Demuxer will use avio_open, no opened file should be provided by the caller.\n#define AVFMT_NOFILE        0x0001\n#define AVFMT_NEEDNUMBER    0x0002 /**< Needs '%d' in filename. */\n/**\n * The muxer/demuxer is experimental and should be used with caution.\n *\n * - demuxers: will not be selected automatically by probing, must be specified\n *             explicitly.\n */\n#define AVFMT_EXPERIMENTAL  0x0004\n#define AVFMT_SHOW_IDS      0x0008 /**< Show format stream IDs numbers. */\n#define AVFMT_GLOBALHEADER  0x0040 /**< Format wants global header. */\n#define AVFMT_NOTIMESTAMPS  0x0080 /**< Format does not need / have any timestamps. */\n#define AVFMT_GENERIC_INDEX 0x0100 /**< Use generic index building code. */\n#define AVFMT_TS_DISCONT    0x0200 /**< Format allows timestamp discontinuities. Note, muxers always require valid (monotone) timestamps */\n#define AVFMT_VARIABLE_FPS  0x0400 /**< Format allows variable fps. */\n#define AVFMT_NODIMENSIONS  0x0800 /**< Format does not need width/height */\n#define AVFMT_NOSTREAMS     0x1000 /**< Format does not require any streams */\n#define AVFMT_NOBINSEARCH   0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */\n#define AVFMT_NOGENSEARCH   0x4000 /**< Format does not allow to fall back on generic search */\n#define AVFMT_NO_BYTE_SEEK  0x8000 /**< Format does not allow seeking by bytes */\n#define AVFMT_ALLOW_FLUSH  0x10000 /**< Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function. */\n#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly\n                                        increasing timestamps, but they must\n                                        still be monotonic */\n#define AVFMT_TS_NEGATIVE  0x40000 /**< Format allows muxing negative\n                                        timestamps. If not set the timestamp\n                                        will be shifted in av_write_frame and\n                                        av_interleaved_write_frame so they\n                                        start from 0.\n                                        The user or muxer can override this through\n                                        AVFormatContext.avoid_negative_ts\n                                        */\n\n#define AVFMT_SEEK_TO_PTS   0x4000000 /**< Seeking is based on PTS */\n\n/**\n * @addtogroup lavf_encoding\n * @{\n */\ntypedef struct AVOutputFormat {\n    const char *name;\n    /**\n     * Descriptive name for the format, meant to be more human-readable\n     * than name. You should use the NULL_IF_CONFIG_SMALL() macro\n     * to define it.\n     */\n    const char *long_name;\n    const char *mime_type;\n    const char *extensions; /**< comma-separated filename extensions */\n    /* output support */\n    enum AVCodecID audio_codec;    /**< default audio codec */\n    enum AVCodecID video_codec;    /**< default video codec */\n    enum AVCodecID subtitle_codec; /**< default subtitle codec */\n    /**\n     * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER,\n     * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS,\n     * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH,\n     * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE\n     */\n    int flags;\n\n    /**\n     * List of supported codec_id-codec_tag pairs, ordered by \"better\n     * choice first\". The arrays are all terminated by AV_CODEC_ID_NONE.\n     */\n    const struct AVCodecTag * const *codec_tag;\n\n\n    const AVClass *priv_class; ///< AVClass for the private context\n\n    /*****************************************************************\n     * No fields below this line are part of the public API. They\n     * may not be used outside of libavformat and can be changed and\n     * removed at will.\n     * New public fields should be added right above.\n     *****************************************************************\n     */\n    /**\n     * size of private data so that it can be allocated in the wrapper\n     */\n    int priv_data_size;\n\n    /**\n     * Internal flags. See FF_FMT_FLAG_* in internal.h.\n     */\n    int flags_internal;\n\n    int (*write_header)(struct AVFormatContext *);\n    /**\n     * Write a packet. If AVFMT_ALLOW_FLUSH is set in flags,\n     * pkt can be NULL in order to flush data buffered in the muxer.\n     * When flushing, return 0 if there still is more data to flush,\n     * or 1 if everything was flushed and there is no more buffered\n     * data.\n     */\n    int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);\n    int (*write_trailer)(struct AVFormatContext *);\n    /**\n     * A format-specific function for interleavement.\n     * If unset, packets will be interleaved by dts.\n     *\n     * @param s           An AVFormatContext for output. pkt will be added to\n     *                    resp. taken from its packet buffer.\n     * @param[in,out] pkt A packet to be interleaved if has_packet is set;\n     *                    also used to return packets. If no packet is returned\n     *                    (e.g. on error), pkt is blank on return.\n     * @param flush       1 if no further packets are available as input and\n     *                    all remaining packets should be output.\n     * @param has_packet  If set, pkt contains a packet to be interleaved\n     *                    on input; otherwise pkt is blank on input.\n     * @return 1 if a packet was output, 0 if no packet could be output,\n     *         < 0 if an error occurred\n     */\n    int (*interleave_packet)(struct AVFormatContext *s, AVPacket *pkt,\n                             int flush, int has_packet);\n    /**\n     * Test if the given codec can be stored in this container.\n     *\n     * @return 1 if the codec is supported, 0 if it is not.\n     *         A negative number if unknown.\n     *         MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC\n     */\n    int (*query_codec)(enum AVCodecID id, int std_compliance);\n\n    void (*get_output_timestamp)(struct AVFormatContext *s, int stream,\n                                 int64_t *dts, int64_t *wall);\n    /**\n     * Allows sending messages from application to device.\n     */\n    int (*control_message)(struct AVFormatContext *s, int type,\n                           void *data, size_t data_size);\n\n    /**\n     * Write an uncoded AVFrame.\n     *\n     * See av_write_uncoded_frame() for details.\n     *\n     * The library will free *frame afterwards, but the muxer can prevent it\n     * by setting the pointer to NULL.\n     */\n    int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,\n                               AVFrame **frame, unsigned flags);\n    /**\n     * Returns device list with it properties.\n     * @see avdevice_list_devices() for more details.\n     */\n    int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);\n    enum AVCodecID data_codec; /**< default data codec */\n    /**\n     * Initialize format. May allocate data here, and set any AVFormatContext or\n     * AVStream parameters that need to be set before packets are sent.\n     * This method must not write output.\n     *\n     * Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure\n     *\n     * Any allocations made here must be freed in deinit().\n     */\n    int (*init)(struct AVFormatContext *);\n    /**\n     * Deinitialize format. If present, this is called whenever the muxer is being\n     * destroyed, regardless of whether or not the header has been written.\n     *\n     * If a trailer is being written, this is called after write_trailer().\n     *\n     * This is called if init() fails as well.\n     */\n    void (*deinit)(struct AVFormatContext *);\n    /**\n     * Set up any necessary bitstream filtering and extract any extra data needed\n     * for the global header.\n     *\n     * @note pkt might have been directly forwarded by a meta-muxer; therefore\n     *       pkt->stream_index as well as the pkt's timebase might be invalid.\n     * Return 0 if more packets from this stream must be checked; 1 if not.\n     */\n    int (*check_bitstream)(struct AVFormatContext *s, struct AVStream *st,\n                           const AVPacket *pkt);\n} AVOutputFormat;\n/**\n * @}\n */\n\n/**\n * @addtogroup lavf_decoding\n * @{\n */\ntypedef struct AVInputFormat {\n    /**\n     * A comma separated list of short names for the format. New names\n     * may be appended with a minor bump.\n     */\n    const char *name;\n\n    /**\n     * Descriptive name for the format, meant to be more human-readable\n     * than name. You should use the NULL_IF_CONFIG_SMALL() macro\n     * to define it.\n     */\n    const char *long_name;\n\n    /**\n     * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,\n     * AVFMT_NOTIMESTAMPS, AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,\n     * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.\n     */\n    int flags;\n\n    /**\n     * If extensions are defined, then no probe is done. You should\n     * usually not use extension format guessing because it is not\n     * reliable enough\n     */\n    const char *extensions;\n\n    const struct AVCodecTag * const *codec_tag;\n\n    const AVClass *priv_class; ///< AVClass for the private context\n\n    /**\n     * Comma-separated list of mime types.\n     * It is used check for matching mime types while probing.\n     * @see av_probe_input_format2\n     */\n    const char *mime_type;\n\n    /*****************************************************************\n     * No fields below this line are part of the public API. They\n     * may not be used outside of libavformat and can be changed and\n     * removed at will.\n     * New public fields should be added right above.\n     *****************************************************************\n     */\n    /**\n     * Raw demuxers store their codec ID here.\n     */\n    int raw_codec_id;\n\n    /**\n     * Size of private data so that it can be allocated in the wrapper.\n     */\n    int priv_data_size;\n\n    /**\n     * Internal flags. See FF_FMT_FLAG_* in internal.h.\n     */\n    int flags_internal;\n\n    /**\n     * Tell if a given file has a chance of being parsed as this format.\n     * The buffer provided is guaranteed to be AVPROBE_PADDING_SIZE bytes\n     * big so you do not have to check for that unless you need more.\n     */\n    int (*read_probe)(const AVProbeData *);\n\n    /**\n     * Read the format header and initialize the AVFormatContext\n     * structure. Return 0 if OK. 'avformat_new_stream' should be\n     * called to create new streams.\n     */\n    int (*read_header)(struct AVFormatContext *);\n\n    /**\n     * Read one packet and put it in 'pkt'. pts and flags are also\n     * set. 'avformat_new_stream' can be called only if the flag\n     * AVFMTCTX_NOHEADER is used and only in the calling thread (not in a\n     * background thread).\n     * @return 0 on success, < 0 on error.\n     *         Upon returning an error, pkt must be unreferenced by the caller.\n     */\n    int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);\n\n    /**\n     * Close the stream. The AVFormatContext and AVStreams are not\n     * freed by this function\n     */\n    int (*read_close)(struct AVFormatContext *);\n\n    /**\n     * Seek to a given timestamp relative to the frames in\n     * stream component stream_index.\n     * @param stream_index Must not be -1.\n     * @param flags Selects which direction should be preferred if no exact\n     *              match is available.\n     * @return >= 0 on success (but not necessarily the new offset)\n     */\n    int (*read_seek)(struct AVFormatContext *,\n                     int stream_index, int64_t timestamp, int flags);\n\n    /**\n     * Get the next timestamp in stream[stream_index].time_base units.\n     * @return the timestamp or AV_NOPTS_VALUE if an error occurred\n     */\n    int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,\n                              int64_t *pos, int64_t pos_limit);\n\n    /**\n     * Start/resume playing - only meaningful if using a network-based format\n     * (RTSP).\n     */\n    int (*read_play)(struct AVFormatContext *);\n\n    /**\n     * Pause playing - only meaningful if using a network-based format\n     * (RTSP).\n     */\n    int (*read_pause)(struct AVFormatContext *);\n\n    /**\n     * Seek to timestamp ts.\n     * Seeking will be done so that the point from which all active streams\n     * can be presented successfully will be closest to ts and within min/max_ts.\n     * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.\n     */\n    int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);\n\n    /**\n     * Returns device list with it properties.\n     * @see avdevice_list_devices() for more details.\n     */\n    int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);\n\n} AVInputFormat;\n/**\n * @}\n */\n\nenum AVStreamParseType {\n    AVSTREAM_PARSE_NONE,\n    AVSTREAM_PARSE_FULL,       /**< full parsing and repack */\n    AVSTREAM_PARSE_HEADERS,    /**< Only parse headers, do not repack. */\n    AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on a packet boundary */\n    AVSTREAM_PARSE_FULL_ONCE,  /**< full parsing and repack of the first frame only, only implemented for H.264 currently */\n    AVSTREAM_PARSE_FULL_RAW,   /**< full parsing and repack with timestamp and position generation by parser for raw\n                                    this assumes that each packet in the file contains no demuxer level headers and\n                                    just codec level data, otherwise position generation would fail */\n};\n\ntypedef struct AVIndexEntry {\n    int64_t pos;\n    int64_t timestamp;        /**<\n                               * Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are available\n                               * when seeking to this entry. That means preferable PTS on keyframe based formats.\n                               * But demuxers can choose to store a different timestamp, if it is more convenient for the implementation or nothing better\n                               * is known\n                               */\n#define AVINDEX_KEYFRAME 0x0001\n#define AVINDEX_DISCARD_FRAME  0x0002    /**\n                                          * Flag is used to indicate which frame should be discarded after decoding.\n                                          */\n    int flags:2;\n    int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs. 32 bytes due to possible 8-byte alignment).\n    int min_distance;         /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */\n} AVIndexEntry;\n\n/**\n * The stream should be chosen by default among other streams of the same type,\n * unless the user has explicitly specified otherwise.\n */\n#define AV_DISPOSITION_DEFAULT              (1 << 0)\n/**\n * The stream is not in original language.\n *\n * @note AV_DISPOSITION_ORIGINAL is the inverse of this disposition. At most\n *       one of them should be set in properly tagged streams.\n * @note This disposition may apply to any stream type, not just audio.\n */\n#define AV_DISPOSITION_DUB                  (1 << 1)\n/**\n * The stream is in original language.\n *\n * @see the notes for AV_DISPOSITION_DUB\n */\n#define AV_DISPOSITION_ORIGINAL             (1 << 2)\n/**\n * The stream is a commentary track.\n */\n#define AV_DISPOSITION_COMMENT              (1 << 3)\n/**\n * The stream contains song lyrics.\n */\n#define AV_DISPOSITION_LYRICS               (1 << 4)\n/**\n * The stream contains karaoke audio.\n */\n#define AV_DISPOSITION_KARAOKE              (1 << 5)\n\n/**\n * Track should be used during playback by default.\n * Useful for subtitle track that should be displayed\n * even when user did not explicitly ask for subtitles.\n */\n#define AV_DISPOSITION_FORCED               (1 << 6)\n/**\n * The stream is intended for hearing impaired audiences.\n */\n#define AV_DISPOSITION_HEARING_IMPAIRED     (1 << 7)\n/**\n * The stream is intended for visually impaired audiences.\n */\n#define AV_DISPOSITION_VISUAL_IMPAIRED      (1 << 8)\n/**\n * The audio stream contains music and sound effects without voice.\n */\n#define AV_DISPOSITION_CLEAN_EFFECTS        (1 << 9)\n/**\n * The stream is stored in the file as an attached picture/\"cover art\" (e.g.\n * APIC frame in ID3v2). The first (usually only) packet associated with it\n * will be returned among the first few packets read from the file unless\n * seeking takes place. It can also be accessed at any time in\n * AVStream.attached_pic.\n */\n#define AV_DISPOSITION_ATTACHED_PIC         (1 << 10)\n/**\n * The stream is sparse, and contains thumbnail images, often corresponding\n * to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC.\n */\n#define AV_DISPOSITION_TIMED_THUMBNAILS     (1 << 11)\n\n/**\n * The stream is intended to be mixed with a spatial audio track. For example,\n * it could be used for narration or stereo music, and may remain unchanged by\n * listener head rotation.\n */\n#define AV_DISPOSITION_NON_DIEGETIC         (1 << 12)\n\n/**\n * The subtitle stream contains captions, providing a transcription and possibly\n * a translation of audio. Typically intended for hearing-impaired audiences.\n */\n#define AV_DISPOSITION_CAPTIONS             (1 << 16)\n/**\n * The subtitle stream contains a textual description of the video content.\n * Typically intended for visually-impaired audiences or for the cases where the\n * video cannot be seen.\n */\n#define AV_DISPOSITION_DESCRIPTIONS         (1 << 17)\n/**\n * The subtitle stream contains time-aligned metadata that is not intended to be\n * directly presented to the user.\n */\n#define AV_DISPOSITION_METADATA             (1 << 18)\n/**\n * The audio stream is intended to be mixed with another stream before\n * presentation.\n * Corresponds to mix_type=0 in mpegts.\n */\n#define AV_DISPOSITION_DEPENDENT            (1 << 19)\n/**\n * The video stream contains still images.\n */\n#define AV_DISPOSITION_STILL_IMAGE          (1 << 20)\n\n/**\n * @return The AV_DISPOSITION_* flag corresponding to disp or a negative error\n *         code if disp does not correspond to a known stream disposition.\n */\nint av_disposition_from_string(const char *disp);\n\n/**\n * @param disposition a combination of AV_DISPOSITION_* values\n * @return The string description corresponding to the lowest set bit in\n *         disposition. NULL when the lowest set bit does not correspond\n *         to a known disposition or when disposition is 0.\n */\nconst char *av_disposition_to_string(int disposition);\n\n/**\n * Options for behavior on timestamp wrap detection.\n */\n#define AV_PTS_WRAP_IGNORE      0   ///< ignore the wrap\n#define AV_PTS_WRAP_ADD_OFFSET  1   ///< add the format specific offset on wrap detection\n#define AV_PTS_WRAP_SUB_OFFSET  -1  ///< subtract the format specific offset on wrap detection\n\n/**\n * Stream structure.\n * New fields can be added to the end with minor version bumps.\n * Removal, reordering and changes to existing fields require a major\n * version bump.\n * sizeof(AVStream) must not be used outside libav*.\n */\ntypedef struct AVStream {\n#if FF_API_AVSTREAM_CLASS\n    /**\n     * A class for @ref avoptions. Set on stream creation.\n     */\n    const AVClass *av_class;\n#endif\n\n    int index;    /**< stream index in AVFormatContext */\n    /**\n     * Format-specific stream ID.\n     * decoding: set by libavformat\n     * encoding: set by the user, replaced by libavformat if left unset\n     */\n    int id;\n\n    void *priv_data;\n\n    /**\n     * This is the fundamental unit of time (in seconds) in terms\n     * of which frame timestamps are represented.\n     *\n     * decoding: set by libavformat\n     * encoding: May be set by the caller before avformat_write_header() to\n     *           provide a hint to the muxer about the desired timebase. In\n     *           avformat_write_header(), the muxer will overwrite this field\n     *           with the timebase that will actually be used for the timestamps\n     *           written into the file (which may or may not be related to the\n     *           user-provided one, depending on the format).\n     */\n    AVRational time_base;\n\n    /**\n     * Decoding: pts of the first frame of the stream in presentation order, in stream time base.\n     * Only set this if you are absolutely 100% sure that the value you set\n     * it to really is the pts of the first frame.\n     * This may be undefined (AV_NOPTS_VALUE).\n     * @note The ASF header does NOT contain a correct start_time the ASF\n     * demuxer must NOT set this.\n     */\n    int64_t start_time;\n\n    /**\n     * Decoding: duration of the stream, in stream time base.\n     * If a source file does not specify a duration, but does specify\n     * a bitrate, this value will be estimated from bitrate and file size.\n     *\n     * Encoding: May be set by the caller before avformat_write_header() to\n     * provide a hint to the muxer about the estimated duration.\n     */\n    int64_t duration;\n\n    int64_t nb_frames;                 ///< number of frames in this stream if known or 0\n\n    /**\n     * Stream disposition - a combination of AV_DISPOSITION_* flags.\n     * - demuxing: set by libavformat when creating the stream or in\n     *             avformat_find_stream_info().\n     * - muxing: may be set by the caller before avformat_write_header().\n     */\n    int disposition;\n\n    enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed.\n\n    /**\n     * sample aspect ratio (0 if unknown)\n     * - encoding: Set by user.\n     * - decoding: Set by libavformat.\n     */\n    AVRational sample_aspect_ratio;\n\n    AVDictionary *metadata;\n\n    /**\n     * Average framerate\n     *\n     * - demuxing: May be set by libavformat when creating the stream or in\n     *             avformat_find_stream_info().\n     * - muxing: May be set by the caller before avformat_write_header().\n     */\n    AVRational avg_frame_rate;\n\n    /**\n     * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet\n     * will contain the attached picture.\n     *\n     * decoding: set by libavformat, must not be modified by the caller.\n     * encoding: unused\n     */\n    AVPacket attached_pic;\n\n    /**\n     * An array of side data that applies to the whole stream (i.e. the\n     * container does not allow it to change between packets).\n     *\n     * There may be no overlap between the side data in this array and side data\n     * in the packets. I.e. a given side data is either exported by the muxer\n     * (demuxing) / set by the caller (muxing) in this array, then it never\n     * appears in the packets, or the side data is exported / sent through\n     * the packets (always in the first packet where the value becomes known or\n     * changes), then it does not appear in this array.\n     *\n     * - demuxing: Set by libavformat when the stream is created.\n     * - muxing: May be set by the caller before avformat_write_header().\n     *\n     * Freed by libavformat in avformat_free_context().\n     *\n     * @see av_format_inject_global_side_data()\n     */\n    AVPacketSideData *side_data;\n    /**\n     * The number of elements in the AVStream.side_data array.\n     */\n    int            nb_side_data;\n\n    /**\n     * Flags indicating events happening on the stream, a combination of\n     * AVSTREAM_EVENT_FLAG_*.\n     *\n     * - demuxing: may be set by the demuxer in avformat_open_input(),\n     *   avformat_find_stream_info() and av_read_frame(). Flags must be cleared\n     *   by the user once the event has been handled.\n     * - muxing: may be set by the user after avformat_write_header(). to\n     *   indicate a user-triggered event.  The muxer will clear the flags for\n     *   events it has handled in av_[interleaved]_write_frame().\n     */\n    int event_flags;\n/**\n * - demuxing: the demuxer read new metadata from the file and updated\n *     AVStream.metadata accordingly\n * - muxing: the user updated AVStream.metadata and wishes the muxer to write\n *     it into the file\n */\n#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001\n/**\n * - demuxing: new packets for this stream were read from the file. This\n *   event is informational only and does not guarantee that new packets\n *   for this stream will necessarily be returned from av_read_frame().\n */\n#define AVSTREAM_EVENT_FLAG_NEW_PACKETS (1 << 1)\n\n    /**\n     * Real base framerate of the stream.\n     * This is the lowest framerate with which all timestamps can be\n     * represented accurately (it is the least common multiple of all\n     * framerates in the stream). Note, this value is just a guess!\n     * For example, if the time base is 1/90000 and all frames have either\n     * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1.\n     */\n    AVRational r_frame_rate;\n\n    /**\n     * Codec parameters associated with this stream. Allocated and freed by\n     * libavformat in avformat_new_stream() and avformat_free_context()\n     * respectively.\n     *\n     * - demuxing: filled by libavformat on stream creation or in\n     *             avformat_find_stream_info()\n     * - muxing: filled by the caller before avformat_write_header()\n     */\n    AVCodecParameters *codecpar;\n\n    /**\n     * Number of bits in timestamps. Used for wrapping control.\n     *\n     * - demuxing: set by libavformat\n     * - muxing: set by libavformat\n     *\n     */\n    int pts_wrap_bits;\n} AVStream;\n\nstruct AVCodecParserContext *av_stream_get_parser(const AVStream *s);\n\n/**\n * Returns the pts of the last muxed packet + its duration\n *\n * the retuned value is undefined when used with a demuxer.\n */\nint64_t    av_stream_get_end_pts(const AVStream *st);\n\n#define AV_PROGRAM_RUNNING 1\n\n/**\n * New fields can be added to the end with minor version bumps.\n * Removal, reordering and changes to existing fields require a major\n * version bump.\n * sizeof(AVProgram) must not be used outside libav*.\n */\ntypedef struct AVProgram {\n    int            id;\n    int            flags;\n    enum AVDiscard discard;        ///< selects which program to discard and which to feed to the caller\n    unsigned int   *stream_index;\n    unsigned int   nb_stream_indexes;\n    AVDictionary *metadata;\n\n    int program_num;\n    int pmt_pid;\n    int pcr_pid;\n    int pmt_version;\n\n    /*****************************************************************\n     * All fields below this line are not part of the public API. They\n     * may not be used outside of libavformat and can be changed and\n     * removed at will.\n     * New public fields should be added right above.\n     *****************************************************************\n     */\n    int64_t start_time;\n    int64_t end_time;\n\n    int64_t pts_wrap_reference;    ///< reference dts for wrap detection\n    int pts_wrap_behavior;         ///< behavior on wrap detection\n} AVProgram;\n\n#define AVFMTCTX_NOHEADER      0x0001 /**< signal that no header is present\n                                         (streams are added dynamically) */\n#define AVFMTCTX_UNSEEKABLE    0x0002 /**< signal that the stream is definitely\n                                         not seekable, and attempts to call the\n                                         seek function will fail. For some\n                                         network protocols (e.g. HLS), this can\n                                         change dynamically at runtime. */\n\ntypedef struct AVChapter {\n    int64_t id;             ///< unique ID to identify the chapter\n    AVRational time_base;   ///< time base in which the start/end timestamps are specified\n    int64_t start, end;     ///< chapter start/end time in time_base units\n    AVDictionary *metadata;\n} AVChapter;\n\n\n/**\n * Callback used by devices to communicate with application.\n */\ntypedef int (*av_format_control_message)(struct AVFormatContext *s, int type,\n                                         void *data, size_t data_size);\n\ntypedef int (*AVOpenCallback)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,\n                              const AVIOInterruptCB *int_cb, AVDictionary **options);\n\n/**\n * The duration of a video can be estimated through various ways, and this enum can be used\n * to know how the duration was estimated.\n */\nenum AVDurationEstimationMethod {\n    AVFMT_DURATION_FROM_PTS,    ///< Duration accurately estimated from PTSes\n    AVFMT_DURATION_FROM_STREAM, ///< Duration estimated from a stream with a known duration\n    AVFMT_DURATION_FROM_BITRATE ///< Duration estimated from bitrate (less accurate)\n};\n\n/**\n * Format I/O context.\n * New fields can be added to the end with minor version bumps.\n * Removal, reordering and changes to existing fields require a major\n * version bump.\n * sizeof(AVFormatContext) must not be used outside libav*, use\n * avformat_alloc_context() to create an AVFormatContext.\n *\n * Fields can be accessed through AVOptions (av_opt*),\n * the name string used matches the associated command line parameter name and\n * can be found in libavformat/options_table.h.\n * The AVOption/command line parameter names differ in some cases from the C\n * structure field names for historic reasons or brevity.\n */\ntypedef struct AVFormatContext {\n    /**\n     * A class for logging and @ref avoptions. Set by avformat_alloc_context().\n     * Exports (de)muxer private options if they exist.\n     */\n    const AVClass *av_class;\n\n    /**\n     * The input container format.\n     *\n     * Demuxing only, set by avformat_open_input().\n     */\n    const struct AVInputFormat *iformat;\n\n    /**\n     * The output container format.\n     *\n     * Muxing only, must be set by the caller before avformat_write_header().\n     */\n    const struct AVOutputFormat *oformat;\n\n    /**\n     * Format private data. This is an AVOptions-enabled struct\n     * if and only if iformat/oformat.priv_class is not NULL.\n     *\n     * - muxing: set by avformat_write_header()\n     * - demuxing: set by avformat_open_input()\n     */\n    void *priv_data;\n\n    /**\n     * I/O context.\n     *\n     * - demuxing: either set by the user before avformat_open_input() (then\n     *             the user must close it manually) or set by avformat_open_input().\n     * - muxing: set by the user before avformat_write_header(). The caller must\n     *           take care of closing / freeing the IO context.\n     *\n     * Do NOT set this field if AVFMT_NOFILE flag is set in\n     * iformat/oformat.flags. In such a case, the (de)muxer will handle\n     * I/O in some other way and this field will be NULL.\n     */\n    AVIOContext *pb;\n\n    /* stream info */\n    /**\n     * Flags signalling stream properties. A combination of AVFMTCTX_*.\n     * Set by libavformat.\n     */\n    int ctx_flags;\n\n    /**\n     * Number of elements in AVFormatContext.streams.\n     *\n     * Set by avformat_new_stream(), must not be modified by any other code.\n     */\n    unsigned int nb_streams;\n    /**\n     * A list of all streams in the file. New streams are created with\n     * avformat_new_stream().\n     *\n     * - demuxing: streams are created by libavformat in avformat_open_input().\n     *             If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also\n     *             appear in av_read_frame().\n     * - muxing: streams are created by the user before avformat_write_header().\n     *\n     * Freed by libavformat in avformat_free_context().\n     */\n    AVStream **streams;\n\n    /**\n     * input or output URL. Unlike the old filename field, this field has no\n     * length restriction.\n     *\n     * - demuxing: set by avformat_open_input(), initialized to an empty\n     *             string if url parameter was NULL in avformat_open_input().\n     * - muxing: may be set by the caller before calling avformat_write_header()\n     *           (or avformat_init_output() if that is called first) to a string\n     *           which is freeable by av_free(). Set to an empty string if it\n     *           was NULL in avformat_init_output().\n     *\n     * Freed by libavformat in avformat_free_context().\n     */\n    char *url;\n\n    /**\n     * Position of the first frame of the component, in\n     * AV_TIME_BASE fractional seconds. NEVER set this value directly:\n     * It is deduced from the AVStream values.\n     *\n     * Demuxing only, set by libavformat.\n     */\n    int64_t start_time;\n\n    /**\n     * Duration of the stream, in AV_TIME_BASE fractional\n     * seconds. Only set this value if you know none of the individual stream\n     * durations and also do not set any of them. This is deduced from the\n     * AVStream values if not set.\n     *\n     * Demuxing only, set by libavformat.\n     */\n    int64_t duration;\n\n    /**\n     * Total stream bitrate in bit/s, 0 if not\n     * available. Never set it directly if the file_size and the\n     * duration are known as FFmpeg can compute it automatically.\n     */\n    int64_t bit_rate;\n\n    unsigned int packet_size;\n    int max_delay;\n\n    /**\n     * Flags modifying the (de)muxer behaviour. A combination of AVFMT_FLAG_*.\n     * Set by the user before avformat_open_input() / avformat_write_header().\n     */\n    int flags;\n#define AVFMT_FLAG_GENPTS       0x0001 ///< Generate missing pts even if it requires parsing future frames.\n#define AVFMT_FLAG_IGNIDX       0x0002 ///< Ignore index.\n#define AVFMT_FLAG_NONBLOCK     0x0004 ///< Do not block when reading packets from input.\n#define AVFMT_FLAG_IGNDTS       0x0008 ///< Ignore DTS on frames that contain both DTS & PTS\n#define AVFMT_FLAG_NOFILLIN     0x0010 ///< Do not infer any values from other values, just return what is stored in the container\n#define AVFMT_FLAG_NOPARSE      0x0020 ///< Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled\n#define AVFMT_FLAG_NOBUFFER     0x0040 ///< Do not buffer frames when possible\n#define AVFMT_FLAG_CUSTOM_IO    0x0080 ///< The caller has supplied a custom AVIOContext, don't avio_close() it.\n#define AVFMT_FLAG_DISCARD_CORRUPT  0x0100 ///< Discard frames marked corrupted\n#define AVFMT_FLAG_FLUSH_PACKETS    0x0200 ///< Flush the AVIOContext every packet.\n/**\n * When muxing, try to avoid writing any random/volatile data to the output.\n * This includes any random IDs, real-time timestamps/dates, muxer version, etc.\n *\n * This flag is mainly intended for testing.\n */\n#define AVFMT_FLAG_BITEXACT         0x0400\n#define AVFMT_FLAG_SORT_DTS    0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down)\n#if FF_API_LAVF_PRIV_OPT\n#define AVFMT_FLAG_PRIV_OPT    0x20000 ///< Enable use of private options by delaying codec open (deprecated, does nothing)\n#endif\n#define AVFMT_FLAG_FAST_SEEK   0x80000 ///< Enable fast, but inaccurate seeks for some formats\n#define AVFMT_FLAG_SHORTEST   0x100000 ///< Stop muxing when the shortest stream stops.\n#define AVFMT_FLAG_AUTO_BSF   0x200000 ///< Add bitstream filters as requested by the muxer\n\n    /**\n     * Maximum number of bytes read from input in order to determine stream\n     * properties. Used when reading the global header and in\n     * avformat_find_stream_info().\n     *\n     * Demuxing only, set by the caller before avformat_open_input().\n     *\n     * @note this is \\e not  used for determining the \\ref AVInputFormat\n     *       \"input format\"\n     * @sa format_probesize\n     */\n    int64_t probesize;\n\n    /**\n     * Maximum duration (in AV_TIME_BASE units) of the data read\n     * from input in avformat_find_stream_info().\n     * Demuxing only, set by the caller before avformat_find_stream_info().\n     * Can be set to 0 to let avformat choose using a heuristic.\n     */\n    int64_t max_analyze_duration;\n\n    const uint8_t *key;\n    int keylen;\n\n    unsigned int nb_programs;\n    AVProgram **programs;\n\n    /**\n     * Forced video codec_id.\n     * Demuxing: Set by user.\n     */\n    enum AVCodecID video_codec_id;\n\n    /**\n     * Forced audio codec_id.\n     * Demuxing: Set by user.\n     */\n    enum AVCodecID audio_codec_id;\n\n    /**\n     * Forced subtitle codec_id.\n     * Demuxing: Set by user.\n     */\n    enum AVCodecID subtitle_codec_id;\n\n    /**\n     * Maximum amount of memory in bytes to use for the index of each stream.\n     * If the index exceeds this size, entries will be discarded as\n     * needed to maintain a smaller size. This can lead to slower or less\n     * accurate seeking (depends on demuxer).\n     * Demuxers for which a full in-memory index is mandatory will ignore\n     * this.\n     * - muxing: unused\n     * - demuxing: set by user\n     */\n    unsigned int max_index_size;\n\n    /**\n     * Maximum amount of memory in bytes to use for buffering frames\n     * obtained from realtime capture devices.\n     */\n    unsigned int max_picture_buffer;\n\n    /**\n     * Number of chapters in AVChapter array.\n     * When muxing, chapters are normally written in the file header,\n     * so nb_chapters should normally be initialized before write_header\n     * is called. Some muxers (e.g. mov and mkv) can also write chapters\n     * in the trailer.  To write chapters in the trailer, nb_chapters\n     * must be zero when write_header is called and non-zero when\n     * write_trailer is called.\n     * - muxing: set by user\n     * - demuxing: set by libavformat\n     */\n    unsigned int nb_chapters;\n    AVChapter **chapters;\n\n    /**\n     * Metadata that applies to the whole file.\n     *\n     * - demuxing: set by libavformat in avformat_open_input()\n     * - muxing: may be set by the caller before avformat_write_header()\n     *\n     * Freed by libavformat in avformat_free_context().\n     */\n    AVDictionary *metadata;\n\n    /**\n     * Start time of the stream in real world time, in microseconds\n     * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the\n     * stream was captured at this real world time.\n     * - muxing: Set by the caller before avformat_write_header(). If set to\n     *           either 0 or AV_NOPTS_VALUE, then the current wall-time will\n     *           be used.\n     * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that\n     *             the value may become known after some number of frames\n     *             have been received.\n     */\n    int64_t start_time_realtime;\n\n    /**\n     * The number of frames used for determining the framerate in\n     * avformat_find_stream_info().\n     * Demuxing only, set by the caller before avformat_find_stream_info().\n     */\n    int fps_probe_size;\n\n    /**\n     * Error recognition; higher values will detect more errors but may\n     * misdetect some more or less valid parts as errors.\n     * Demuxing only, set by the caller before avformat_open_input().\n     */\n    int error_recognition;\n\n    /**\n     * Custom interrupt callbacks for the I/O layer.\n     *\n     * demuxing: set by the user before avformat_open_input().\n     * muxing: set by the user before avformat_write_header()\n     * (mainly useful for AVFMT_NOFILE formats). The callback\n     * should also be passed to avio_open2() if it's used to\n     * open the file.\n     */\n    AVIOInterruptCB interrupt_callback;\n\n    /**\n     * Flags to enable debugging.\n     */\n    int debug;\n#define FF_FDEBUG_TS        0x0001\n\n    /**\n     * Maximum buffering duration for interleaving.\n     *\n     * To ensure all the streams are interleaved correctly,\n     * av_interleaved_write_frame() will wait until it has at least one packet\n     * for each stream before actually writing any packets to the output file.\n     * When some streams are \"sparse\" (i.e. there are large gaps between\n     * successive packets), this can result in excessive buffering.\n     *\n     * This field specifies the maximum difference between the timestamps of the\n     * first and the last packet in the muxing queue, above which libavformat\n     * will output a packet regardless of whether it has queued a packet for all\n     * the streams.\n     *\n     * Muxing only, set by the caller before avformat_write_header().\n     */\n    int64_t max_interleave_delta;\n\n    /**\n     * Allow non-standard and experimental extension\n     * @see AVCodecContext.strict_std_compliance\n     */\n    int strict_std_compliance;\n\n    /**\n     * Flags indicating events happening on the file, a combination of\n     * AVFMT_EVENT_FLAG_*.\n     *\n     * - demuxing: may be set by the demuxer in avformat_open_input(),\n     *   avformat_find_stream_info() and av_read_frame(). Flags must be cleared\n     *   by the user once the event has been handled.\n     * - muxing: may be set by the user after avformat_write_header() to\n     *   indicate a user-triggered event.  The muxer will clear the flags for\n     *   events it has handled in av_[interleaved]_write_frame().\n     */\n    int event_flags;\n/**\n * - demuxing: the demuxer read new metadata from the file and updated\n *   AVFormatContext.metadata accordingly\n * - muxing: the user updated AVFormatContext.metadata and wishes the muxer to\n *   write it into the file\n */\n#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001\n\n    /**\n     * Maximum number of packets to read while waiting for the first timestamp.\n     * Decoding only.\n     */\n    int max_ts_probe;\n\n    /**\n     * Avoid negative timestamps during muxing.\n     * Any value of the AVFMT_AVOID_NEG_TS_* constants.\n     * Note, this works better when using av_interleaved_write_frame().\n     * - muxing: Set by user\n     * - demuxing: unused\n     */\n    int avoid_negative_ts;\n#define AVFMT_AVOID_NEG_TS_AUTO             -1 ///< Enabled when required by target format\n#define AVFMT_AVOID_NEG_TS_DISABLED          0 ///< Do not shift timestamps even when they are negative.\n#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative\n#define AVFMT_AVOID_NEG_TS_MAKE_ZERO         2 ///< Shift timestamps so that they start at 0\n\n    /**\n     * Transport stream id.\n     * This will be moved into demuxer private options. Thus no API/ABI compatibility\n     */\n    int ts_id;\n\n    /**\n     * Audio preload in microseconds.\n     * Note, not all formats support this and unpredictable things may happen if it is used when not supported.\n     * - encoding: Set by user\n     * - decoding: unused\n     */\n    int audio_preload;\n\n    /**\n     * Max chunk time in microseconds.\n     * Note, not all formats support this and unpredictable things may happen if it is used when not supported.\n     * - encoding: Set by user\n     * - decoding: unused\n     */\n    int max_chunk_duration;\n\n    /**\n     * Max chunk size in bytes\n     * Note, not all formats support this and unpredictable things may happen if it is used when not supported.\n     * - encoding: Set by user\n     * - decoding: unused\n     */\n    int max_chunk_size;\n\n    /**\n     * forces the use of wallclock timestamps as pts/dts of packets\n     * This has undefined results in the presence of B frames.\n     * - encoding: unused\n     * - decoding: Set by user\n     */\n    int use_wallclock_as_timestamps;\n\n    /**\n     * avio flags, used to force AVIO_FLAG_DIRECT.\n     * - encoding: unused\n     * - decoding: Set by user\n     */\n    int avio_flags;\n\n    /**\n     * The duration field can be estimated through various ways, and this field can be used\n     * to know how the duration was estimated.\n     * - encoding: unused\n     * - decoding: Read by user\n     */\n    enum AVDurationEstimationMethod duration_estimation_method;\n\n    /**\n     * Skip initial bytes when opening stream\n     * - encoding: unused\n     * - decoding: Set by user\n     */\n    int64_t skip_initial_bytes;\n\n    /**\n     * Correct single timestamp overflows\n     * - encoding: unused\n     * - decoding: Set by user\n     */\n    unsigned int correct_ts_overflow;\n\n    /**\n     * Force seeking to any (also non key) frames.\n     * - encoding: unused\n     * - decoding: Set by user\n     */\n    int seek2any;\n\n    /**\n     * Flush the I/O context after each packet.\n     * - encoding: Set by user\n     * - decoding: unused\n     */\n    int flush_packets;\n\n    /**\n     * format probing score.\n     * The maximal score is AVPROBE_SCORE_MAX, its set when the demuxer probes\n     * the format.\n     * - encoding: unused\n     * - decoding: set by avformat, read by user\n     */\n    int probe_score;\n\n    /**\n     * Maximum number of bytes read from input in order to identify the\n     * \\ref AVInputFormat \"input format\". Only used when the format is not set\n     * explicitly by the caller.\n     *\n     * Demuxing only, set by the caller before avformat_open_input().\n     *\n     * @sa probesize\n     */\n    int format_probesize;\n\n    /**\n     * ',' separated list of allowed decoders.\n     * If NULL then all are allowed\n     * - encoding: unused\n     * - decoding: set by user\n     */\n    char *codec_whitelist;\n\n    /**\n     * ',' separated list of allowed demuxers.\n     * If NULL then all are allowed\n     * - encoding: unused\n     * - decoding: set by user\n     */\n    char *format_whitelist;\n\n    /**\n     * IO repositioned flag.\n     * This is set by avformat when the underlaying IO context read pointer\n     * is repositioned, for example when doing byte based seeking.\n     * Demuxers can use the flag to detect such changes.\n     */\n    int io_repositioned;\n\n    /**\n     * Forced video codec.\n     * This allows forcing a specific decoder, even when there are multiple with\n     * the same codec_id.\n     * Demuxing: Set by user\n     */\n    const AVCodec *video_codec;\n\n    /**\n     * Forced audio codec.\n     * This allows forcing a specific decoder, even when there are multiple with\n     * the same codec_id.\n     * Demuxing: Set by user\n     */\n    const AVCodec *audio_codec;\n\n    /**\n     * Forced subtitle codec.\n     * This allows forcing a specific decoder, even when there are multiple with\n     * the same codec_id.\n     * Demuxing: Set by user\n     */\n    const AVCodec *subtitle_codec;\n\n    /**\n     * Forced data codec.\n     * This allows forcing a specific decoder, even when there are multiple with\n     * the same codec_id.\n     * Demuxing: Set by user\n     */\n    const AVCodec *data_codec;\n\n    /**\n     * Number of bytes to be written as padding in a metadata header.\n     * Demuxing: Unused.\n     * Muxing: Set by user via av_format_set_metadata_header_padding.\n     */\n    int metadata_header_padding;\n\n    /**\n     * User data.\n     * This is a place for some private data of the user.\n     */\n    void *opaque;\n\n    /**\n     * Callback used by devices to communicate with application.\n     */\n    av_format_control_message control_message_cb;\n\n    /**\n     * Output timestamp offset, in microseconds.\n     * Muxing: set by user\n     */\n    int64_t output_ts_offset;\n\n    /**\n     * dump format separator.\n     * can be \", \" or \"\\n      \" or anything else\n     * - muxing: Set by user.\n     * - demuxing: Set by user.\n     */\n    uint8_t *dump_separator;\n\n    /**\n     * Forced Data codec_id.\n     * Demuxing: Set by user.\n     */\n    enum AVCodecID data_codec_id;\n\n    /**\n     * ',' separated list of allowed protocols.\n     * - encoding: unused\n     * - decoding: set by user\n     */\n    char *protocol_whitelist;\n\n    /**\n     * A callback for opening new IO streams.\n     *\n     * Whenever a muxer or a demuxer needs to open an IO stream (typically from\n     * avformat_open_input() for demuxers, but for certain formats can happen at\n     * other times as well), it will call this callback to obtain an IO context.\n     *\n     * @param s the format context\n     * @param pb on success, the newly opened IO context should be returned here\n     * @param url the url to open\n     * @param flags a combination of AVIO_FLAG_*\n     * @param options a dictionary of additional options, with the same\n     *                semantics as in avio_open2()\n     * @return 0 on success, a negative AVERROR code on failure\n     *\n     * @note Certain muxers and demuxers do nesting, i.e. they open one or more\n     * additional internal format contexts. Thus the AVFormatContext pointer\n     * passed to this callback may be different from the one facing the caller.\n     * It will, however, have the same 'opaque' field.\n     */\n    int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url,\n                   int flags, AVDictionary **options);\n\n    /**\n     * A callback for closing the streams opened with AVFormatContext.io_open().\n     */\n    void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);\n\n    /**\n     * ',' separated list of disallowed protocols.\n     * - encoding: unused\n     * - decoding: set by user\n     */\n    char *protocol_blacklist;\n\n    /**\n     * The maximum number of streams.\n     * - encoding: unused\n     * - decoding: set by user\n     */\n    int max_streams;\n\n    /**\n     * Skip duration calcuation in estimate_timings_from_pts.\n     * - encoding: unused\n     * - decoding: set by user\n     */\n    int skip_estimate_duration_from_pts;\n\n    /**\n     * Maximum number of packets that can be probed\n     * - encoding: unused\n     * - decoding: set by user\n     */\n    int max_probe_packets;\n\n    /**\n     * A callback for closing the streams opened with AVFormatContext.io_open().\n     *\n     * Using this is preferred over io_close, because this can return an error.\n     * Therefore this callback is used instead of io_close by the generic\n     * libavformat code if io_close is NULL or the default.\n     *\n     * @param s the format context\n     * @param pb IO context to be closed and freed\n     * @return 0 on success, a negative AVERROR code on failure\n     */\n    int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb);\n} AVFormatContext;\n\n/**\n * This function will cause global side data to be injected in the next packet\n * of each stream as well as after any subsequent seek.\n */\nvoid av_format_inject_global_side_data(AVFormatContext *s);\n\n/**\n * Returns the method used to set ctx->duration.\n *\n * @return AVFMT_DURATION_FROM_PTS, AVFMT_DURATION_FROM_STREAM, or AVFMT_DURATION_FROM_BITRATE.\n */\nenum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx);\n\n/**\n * @defgroup lavf_core Core functions\n * @ingroup libavf\n *\n * Functions for querying libavformat capabilities, allocating core structures,\n * etc.\n * @{\n */\n\n/**\n * Return the LIBAVFORMAT_VERSION_INT constant.\n */\nunsigned avformat_version(void);\n\n/**\n * Return the libavformat build-time configuration.\n */\nconst char *avformat_configuration(void);\n\n/**\n * Return the libavformat license.\n */\nconst char *avformat_license(void);\n\n/**\n * Do global initialization of network libraries. This is optional,\n * and not recommended anymore.\n *\n * This functions only exists to work around thread-safety issues\n * with older GnuTLS or OpenSSL libraries. If libavformat is linked\n * to newer versions of those libraries, or if you do not use them,\n * calling this function is unnecessary. Otherwise, you need to call\n * this function before any other threads using them are started.\n *\n * This function will be deprecated once support for older GnuTLS and\n * OpenSSL libraries is removed, and this function has no purpose\n * anymore.\n */\nint avformat_network_init(void);\n\n/**\n * Undo the initialization done by avformat_network_init. Call it only\n * once for each time you called avformat_network_init.\n */\nint avformat_network_deinit(void);\n\n/**\n * Iterate over all registered muxers.\n *\n * @param opaque a pointer where libavformat will store the iteration state. Must\n *               point to NULL to start the iteration.\n *\n * @return the next registered muxer or NULL when the iteration is\n *         finished\n */\nconst AVOutputFormat *av_muxer_iterate(void **opaque);\n\n/**\n * Iterate over all registered demuxers.\n *\n * @param opaque a pointer where libavformat will store the iteration state. Must\n *               point to NULL to start the iteration.\n *\n * @return the next registered demuxer or NULL when the iteration is\n *         finished\n */\nconst AVInputFormat *av_demuxer_iterate(void **opaque);\n\n/**\n * Allocate an AVFormatContext.\n * avformat_free_context() can be used to free the context and everything\n * allocated by the framework within it.\n */\nAVFormatContext *avformat_alloc_context(void);\n\n/**\n * Free an AVFormatContext and all its streams.\n * @param s context to free\n */\nvoid avformat_free_context(AVFormatContext *s);\n\n/**\n * Get the AVClass for AVFormatContext. It can be used in combination with\n * AV_OPT_SEARCH_FAKE_OBJ for examining options.\n *\n * @see av_opt_find().\n */\nconst AVClass *avformat_get_class(void);\n\n/**\n * Get the AVClass for AVStream. It can be used in combination with\n * AV_OPT_SEARCH_FAKE_OBJ for examining options.\n *\n * @see av_opt_find().\n */\nconst AVClass *av_stream_get_class(void);\n\n/**\n * Add a new stream to a media file.\n *\n * When demuxing, it is called by the demuxer in read_header(). If the\n * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also\n * be called in read_packet().\n *\n * When muxing, should be called by the user before avformat_write_header().\n *\n * User is required to call avformat_free_context() to clean up the allocation\n * by avformat_new_stream().\n *\n * @param s media file handle\n * @param c unused, does nothing\n *\n * @return newly created stream or NULL on error.\n */\nAVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);\n\n/**\n * Wrap an existing array as stream side data.\n *\n * @param st stream\n * @param type side information type\n * @param data the side data array. It must be allocated with the av_malloc()\n *             family of functions. The ownership of the data is transferred to\n *             st.\n * @param size side information size\n * @return zero on success, a negative AVERROR code on failure. On failure,\n *         the stream is unchanged and the data remains owned by the caller.\n */\nint av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type,\n                            uint8_t *data, size_t size);\n\n/**\n * Allocate new information from stream.\n *\n * @param stream stream\n * @param type desired side information type\n * @param size side information size\n * @return pointer to fresh allocated data or NULL otherwise\n */\nuint8_t *av_stream_new_side_data(AVStream *stream,\n                                 enum AVPacketSideDataType type, size_t size);\n/**\n * Get side information from stream.\n *\n * @param stream stream\n * @param type desired side information type\n * @param size If supplied, *size will be set to the size of the side data\n *             or to zero if the desired side data is not present.\n * @return pointer to data if present or NULL otherwise\n */\nuint8_t *av_stream_get_side_data(const AVStream *stream,\n                                 enum AVPacketSideDataType type, size_t *size);\n\nAVProgram *av_new_program(AVFormatContext *s, int id);\n\n/**\n * @}\n */\n\n\n/**\n * Allocate an AVFormatContext for an output format.\n * avformat_free_context() can be used to free the context and\n * everything allocated by the framework within it.\n *\n * @param *ctx is set to the created format context, or to NULL in\n * case of failure\n * @param oformat format to use for allocating the context, if NULL\n * format_name and filename are used instead\n * @param format_name the name of output format to use for allocating the\n * context, if NULL filename is used instead\n * @param filename the name of the filename to use for allocating the\n * context, may be NULL\n * @return >= 0 in case of success, a negative AVERROR code in case of\n * failure\n */\nint avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat,\n                                   const char *format_name, const char *filename);\n\n/**\n * @addtogroup lavf_decoding\n * @{\n */\n\n/**\n * Find AVInputFormat based on the short name of the input format.\n */\nconst AVInputFormat *av_find_input_format(const char *short_name);\n\n/**\n * Guess the file format.\n *\n * @param pd        data to be probed\n * @param is_opened Whether the file is already opened; determines whether\n *                  demuxers with or without AVFMT_NOFILE are probed.\n */\nconst AVInputFormat *av_probe_input_format(const AVProbeData *pd, int is_opened);\n\n/**\n * Guess the file format.\n *\n * @param pd        data to be probed\n * @param is_opened Whether the file is already opened; determines whether\n *                  demuxers with or without AVFMT_NOFILE are probed.\n * @param score_max A probe score larger that this is required to accept a\n *                  detection, the variable is set to the actual detection\n *                  score afterwards.\n *                  If the score is <= AVPROBE_SCORE_MAX / 4 it is recommended\n *                  to retry with a larger probe buffer.\n */\nconst AVInputFormat *av_probe_input_format2(const AVProbeData *pd,\n                                            int is_opened, int *score_max);\n\n/**\n * Guess the file format.\n *\n * @param is_opened Whether the file is already opened; determines whether\n *                  demuxers with or without AVFMT_NOFILE are probed.\n * @param score_ret The score of the best detection.\n */\nconst AVInputFormat *av_probe_input_format3(const AVProbeData *pd,\n                                            int is_opened, int *score_ret);\n\n/**\n * Probe a bytestream to determine the input format. Each time a probe returns\n * with a score that is too low, the probe buffer size is increased and another\n * attempt is made. When the maximum probe size is reached, the input format\n * with the highest score is returned.\n *\n * @param pb the bytestream to probe\n * @param fmt the input format is put here\n * @param url the url of the stream\n * @param logctx the log context\n * @param offset the offset within the bytestream to probe from\n * @param max_probe_size the maximum probe buffer size (zero for default)\n * @return the score in case of success, a negative value corresponding to an\n *         the maximal score is AVPROBE_SCORE_MAX\n * AVERROR code otherwise\n */\nint av_probe_input_buffer2(AVIOContext *pb, const AVInputFormat **fmt,\n                           const char *url, void *logctx,\n                           unsigned int offset, unsigned int max_probe_size);\n\n/**\n * Like av_probe_input_buffer2() but returns 0 on success\n */\nint av_probe_input_buffer(AVIOContext *pb, const AVInputFormat **fmt,\n                          const char *url, void *logctx,\n                          unsigned int offset, unsigned int max_probe_size);\n\n/**\n * Open an input stream and read the header. The codecs are not opened.\n * The stream must be closed with avformat_close_input().\n *\n * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).\n *           May be a pointer to NULL, in which case an AVFormatContext is allocated by this\n *           function and written into ps.\n *           Note that a user-supplied AVFormatContext will be freed on failure.\n * @param url URL of the stream to open.\n * @param fmt If non-NULL, this parameter forces a specific input format.\n *            Otherwise the format is autodetected.\n * @param options  A dictionary filled with AVFormatContext and demuxer-private options.\n *                 On return this parameter will be destroyed and replaced with a dict containing\n *                 options that were not found. May be NULL.\n *\n * @return 0 on success, a negative AVERROR on failure.\n *\n * @note If you want to use custom IO, preallocate the format context and set its pb field.\n */\nint avformat_open_input(AVFormatContext **ps, const char *url,\n                        const AVInputFormat *fmt, AVDictionary **options);\n\n/**\n * Read packets of a media file to get stream information. This\n * is useful for file formats with no headers such as MPEG. This\n * function also computes the real framerate in case of MPEG-2 repeat\n * frame mode.\n * The logical file position is not changed by this function;\n * examined packets may be buffered for later processing.\n *\n * @param ic media file handle\n * @param options  If non-NULL, an ic.nb_streams long array of pointers to\n *                 dictionaries, where i-th member contains options for\n *                 codec corresponding to i-th stream.\n *                 On return each dictionary will be filled with options that were not found.\n * @return >=0 if OK, AVERROR_xxx on error\n *\n * @note this function isn't guaranteed to open all the codecs, so\n *       options being non-empty at return is a perfectly normal behavior.\n *\n * @todo Let the user decide somehow what information is needed so that\n *       we do not waste time getting stuff the user does not need.\n */\nint avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);\n\n/**\n * Find the programs which belong to a given stream.\n *\n * @param ic    media file handle\n * @param last  the last found program, the search will start after this\n *              program, or from the beginning if it is NULL\n * @param s     stream index\n * @return the next program which belongs to s, NULL if no program is found or\n *         the last program is not among the programs of ic.\n */\nAVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s);\n\nvoid av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx);\n\n/**\n * Find the \"best\" stream in the file.\n * The best stream is determined according to various heuristics as the most\n * likely to be what the user expects.\n * If the decoder parameter is non-NULL, av_find_best_stream will find the\n * default decoder for the stream's codec; streams for which no decoder can\n * be found are ignored.\n *\n * @param ic                media file handle\n * @param type              stream type: video, audio, subtitles, etc.\n * @param wanted_stream_nb  user-requested stream number,\n *                          or -1 for automatic selection\n * @param related_stream    try to find a stream related (eg. in the same\n *                          program) to this one, or -1 if none\n * @param decoder_ret       if non-NULL, returns the decoder for the\n *                          selected stream\n * @param flags             flags; none are currently defined\n * @return  the non-negative stream number in case of success,\n *          AVERROR_STREAM_NOT_FOUND if no stream with the requested type\n *          could be found,\n *          AVERROR_DECODER_NOT_FOUND if streams were found but no decoder\n * @note  If av_find_best_stream returns successfully and decoder_ret is not\n *        NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec.\n */\nint av_find_best_stream(AVFormatContext *ic,\n                        enum AVMediaType type,\n                        int wanted_stream_nb,\n                        int related_stream,\n                        const AVCodec **decoder_ret,\n                        int flags);\n\n/**\n * Return the next frame of a stream.\n * This function returns what is stored in the file, and does not validate\n * that what is there are valid frames for the decoder. It will split what is\n * stored in the file into frames and return one for each call. It will not\n * omit invalid data between valid frames so as to give the decoder the maximum\n * information possible for decoding.\n *\n * On success, the returned packet is reference-counted (pkt->buf is set) and\n * valid indefinitely. The packet must be freed with av_packet_unref() when\n * it is no longer needed. For video, the packet contains exactly one frame.\n * For audio, it contains an integer number of frames if each frame has\n * a known fixed size (e.g. PCM or ADPCM data). If the audio frames have\n * a variable size (e.g. MPEG audio), then it contains one frame.\n *\n * pkt->pts, pkt->dts and pkt->duration are always set to correct\n * values in AVStream.time_base units (and guessed if the format cannot\n * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format\n * has B-frames, so it is better to rely on pkt->dts if you do not\n * decompress the payload.\n *\n * @return 0 if OK, < 0 on error or end of file. On error, pkt will be blank\n *         (as if it came from av_packet_alloc()).\n *\n * @note pkt will be initialized, so it may be uninitialized, but it must not\n *       contain data that needs to be freed.\n */\nint av_read_frame(AVFormatContext *s, AVPacket *pkt);\n\n/**\n * Seek to the keyframe at timestamp.\n * 'timestamp' in 'stream_index'.\n *\n * @param s media file handle\n * @param stream_index If stream_index is (-1), a default\n * stream is selected, and timestamp is automatically converted\n * from AV_TIME_BASE units to the stream specific time_base.\n * @param timestamp Timestamp in AVStream.time_base units\n *        or, if no stream is specified, in AV_TIME_BASE units.\n * @param flags flags which select direction and seeking mode\n * @return >= 0 on success\n */\nint av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,\n                  int flags);\n\n/**\n * Seek to timestamp ts.\n * Seeking will be done so that the point from which all active streams\n * can be presented successfully will be closest to ts and within min/max_ts.\n * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.\n *\n * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and\n * are the file position (this may not be supported by all demuxers).\n * If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames\n * in the stream with stream_index (this may not be supported by all demuxers).\n * Otherwise all timestamps are in units of the stream selected by stream_index\n * or if stream_index is -1, in AV_TIME_BASE units.\n * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as\n * keyframes (this may not be supported by all demuxers).\n * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored.\n *\n * @param s media file handle\n * @param stream_index index of the stream which is used as time base reference\n * @param min_ts smallest acceptable timestamp\n * @param ts target timestamp\n * @param max_ts largest acceptable timestamp\n * @param flags flags\n * @return >=0 on success, error code otherwise\n *\n * @note This is part of the new seek API which is still under construction.\n */\nint avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);\n\n/**\n * Discard all internally buffered data. This can be useful when dealing with\n * discontinuities in the byte stream. Generally works only with formats that\n * can resync. This includes headerless formats like MPEG-TS/TS but should also\n * work with NUT, Ogg and in a limited way AVI for example.\n *\n * The set of streams, the detected duration, stream parameters and codecs do\n * not change when calling this function. If you want a complete reset, it's\n * better to open a new AVFormatContext.\n *\n * This does not flush the AVIOContext (s->pb). If necessary, call\n * avio_flush(s->pb) before calling this function.\n *\n * @param s media file handle\n * @return >=0 on success, error code otherwise\n */\nint avformat_flush(AVFormatContext *s);\n\n/**\n * Start playing a network-based stream (e.g. RTSP stream) at the\n * current position.\n */\nint av_read_play(AVFormatContext *s);\n\n/**\n * Pause a network-based stream (e.g. RTSP stream).\n *\n * Use av_read_play() to resume it.\n */\nint av_read_pause(AVFormatContext *s);\n\n/**\n * Close an opened input AVFormatContext. Free it and all its contents\n * and set *s to NULL.\n */\nvoid avformat_close_input(AVFormatContext **s);\n/**\n * @}\n */\n\n#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward\n#define AVSEEK_FLAG_BYTE     2 ///< seeking based on position in bytes\n#define AVSEEK_FLAG_ANY      4 ///< seek to any frame, even non-keyframes\n#define AVSEEK_FLAG_FRAME    8 ///< seeking based on frame number\n\n/**\n * @addtogroup lavf_encoding\n * @{\n */\n\n#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header\n#define AVSTREAM_INIT_IN_INIT_OUTPUT  1 ///< stream parameters initialized in avformat_init_output\n\n/**\n * Allocate the stream private data and write the stream header to\n * an output media file.\n *\n * @param s Media file handle, must be allocated with avformat_alloc_context().\n *          Its oformat field must be set to the desired output format;\n *          Its pb field must be set to an already opened AVIOContext.\n * @param options  An AVDictionary filled with AVFormatContext and muxer-private options.\n *                 On return this parameter will be destroyed and replaced with a dict containing\n *                 options that were not found. May be NULL.\n *\n * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init,\n *         AVSTREAM_INIT_IN_INIT_OUTPUT  on success if the codec had already been fully initialized in avformat_init,\n *         negative AVERROR on failure.\n *\n * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output.\n */\nav_warn_unused_result\nint avformat_write_header(AVFormatContext *s, AVDictionary **options);\n\n/**\n * Allocate the stream private data and initialize the codec, but do not write the header.\n * May optionally be used before avformat_write_header to initialize stream parameters\n * before actually writing the header.\n * If using this function, do not pass the same options to avformat_write_header.\n *\n * @param s Media file handle, must be allocated with avformat_alloc_context().\n *          Its oformat field must be set to the desired output format;\n *          Its pb field must be set to an already opened AVIOContext.\n * @param options  An AVDictionary filled with AVFormatContext and muxer-private options.\n *                 On return this parameter will be destroyed and replaced with a dict containing\n *                 options that were not found. May be NULL.\n *\n * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec requires avformat_write_header to fully initialize,\n *         AVSTREAM_INIT_IN_INIT_OUTPUT  on success if the codec has been fully initialized,\n *         negative AVERROR on failure.\n *\n * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header.\n */\nav_warn_unused_result\nint avformat_init_output(AVFormatContext *s, AVDictionary **options);\n\n/**\n * Write a packet to an output media file.\n *\n * This function passes the packet directly to the muxer, without any buffering\n * or reordering. The caller is responsible for correctly interleaving the\n * packets if the format requires it. Callers that want libavformat to handle\n * the interleaving should call av_interleaved_write_frame() instead of this\n * function.\n *\n * @param s media file handle\n * @param pkt The packet containing the data to be written. Note that unlike\n *            av_interleaved_write_frame(), this function does not take\n *            ownership of the packet passed to it (though some muxers may make\n *            an internal reference to the input packet).\n *            <br>\n *            This parameter can be NULL (at any time, not just at the end), in\n *            order to immediately flush data buffered within the muxer, for\n *            muxers that buffer up data internally before writing it to the\n *            output.\n *            <br>\n *            Packet's @ref AVPacket.stream_index \"stream_index\" field must be\n *            set to the index of the corresponding stream in @ref\n *            AVFormatContext.streams \"s->streams\".\n *            <br>\n *            The timestamps (@ref AVPacket.pts \"pts\", @ref AVPacket.dts \"dts\")\n *            must be set to correct values in the stream's timebase (unless the\n *            output format is flagged with the AVFMT_NOTIMESTAMPS flag, then\n *            they can be set to AV_NOPTS_VALUE).\n *            The dts for subsequent packets passed to this function must be strictly\n *            increasing when compared in their respective timebases (unless the\n *            output format is flagged with the AVFMT_TS_NONSTRICT, then they\n *            merely have to be nondecreasing).  @ref AVPacket.duration\n *            \"duration\") should also be set if known.\n * @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush\n *\n * @see av_interleaved_write_frame()\n */\nint av_write_frame(AVFormatContext *s, AVPacket *pkt);\n\n/**\n * Write a packet to an output media file ensuring correct interleaving.\n *\n * This function will buffer the packets internally as needed to make sure the\n * packets in the output file are properly interleaved, usually ordered by\n * increasing dts. Callers doing their own interleaving should call\n * av_write_frame() instead of this function.\n *\n * Using this function instead of av_write_frame() can give muxers advance\n * knowledge of future packets, improving e.g. the behaviour of the mp4\n * muxer for VFR content in fragmenting mode.\n *\n * @param s media file handle\n * @param pkt The packet containing the data to be written.\n *            <br>\n *            If the packet is reference-counted, this function will take\n *            ownership of this reference and unreference it later when it sees\n *            fit. If the packet is not reference-counted, libavformat will\n *            make a copy.\n *            The returned packet will be blank (as if returned from\n *            av_packet_alloc()), even on error.\n *            <br>\n *            This parameter can be NULL (at any time, not just at the end), to\n *            flush the interleaving queues.\n *            <br>\n *            Packet's @ref AVPacket.stream_index \"stream_index\" field must be\n *            set to the index of the corresponding stream in @ref\n *            AVFormatContext.streams \"s->streams\".\n *            <br>\n *            The timestamps (@ref AVPacket.pts \"pts\", @ref AVPacket.dts \"dts\")\n *            must be set to correct values in the stream's timebase (unless the\n *            output format is flagged with the AVFMT_NOTIMESTAMPS flag, then\n *            they can be set to AV_NOPTS_VALUE).\n *            The dts for subsequent packets in one stream must be strictly\n *            increasing (unless the output format is flagged with the\n *            AVFMT_TS_NONSTRICT, then they merely have to be nondecreasing).\n *            @ref AVPacket.duration \"duration\" should also be set if known.\n *\n * @return 0 on success, a negative AVERROR on error.\n *\n * @see av_write_frame(), AVFormatContext.max_interleave_delta\n */\nint av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);\n\n/**\n * Write an uncoded frame to an output media file.\n *\n * The frame must be correctly interleaved according to the container\n * specification; if not, av_interleaved_write_uncoded_frame() must be used.\n *\n * See av_interleaved_write_uncoded_frame() for details.\n */\nint av_write_uncoded_frame(AVFormatContext *s, int stream_index,\n                           AVFrame *frame);\n\n/**\n * Write an uncoded frame to an output media file.\n *\n * If the muxer supports it, this function makes it possible to write an AVFrame\n * structure directly, without encoding it into a packet.\n * It is mostly useful for devices and similar special muxers that use raw\n * video or PCM data and will not serialize it into a byte stream.\n *\n * To test whether it is possible to use it with a given muxer and stream,\n * use av_write_uncoded_frame_query().\n *\n * The caller gives up ownership of the frame and must not access it\n * afterwards.\n *\n * @return  >=0 for success, a negative code on error\n */\nint av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index,\n                                       AVFrame *frame);\n\n/**\n * Test whether a muxer supports uncoded frame.\n *\n * @return  >=0 if an uncoded frame can be written to that muxer and stream,\n *          <0 if not\n */\nint av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);\n\n/**\n * Write the stream trailer to an output media file and free the\n * file private data.\n *\n * May only be called after a successful call to avformat_write_header.\n *\n * @param s media file handle\n * @return 0 if OK, AVERROR_xxx on error\n */\nint av_write_trailer(AVFormatContext *s);\n\n/**\n * Return the output format in the list of registered output formats\n * which best matches the provided parameters, or return NULL if\n * there is no match.\n *\n * @param short_name if non-NULL checks if short_name matches with the\n * names of the registered formats\n * @param filename if non-NULL checks if filename terminates with the\n * extensions of the registered formats\n * @param mime_type if non-NULL checks if mime_type matches with the\n * MIME type of the registered formats\n */\nconst AVOutputFormat *av_guess_format(const char *short_name,\n                                      const char *filename,\n                                      const char *mime_type);\n\n/**\n * Guess the codec ID based upon muxer and filename.\n */\nenum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name,\n                              const char *filename, const char *mime_type,\n                              enum AVMediaType type);\n\n/**\n * Get timing information for the data currently output.\n * The exact meaning of \"currently output\" depends on the format.\n * It is mostly relevant for devices that have an internal buffer and/or\n * work in real time.\n * @param s          media file handle\n * @param stream     stream in the media file\n * @param[out] dts   DTS of the last packet output for the stream, in stream\n *                   time_base units\n * @param[out] wall  absolute time when that packet whas output,\n *                   in microsecond\n * @return  0 if OK, AVERROR(ENOSYS) if the format does not support it\n * Note: some formats or devices may not allow to measure dts and wall\n * atomically.\n */\nint av_get_output_timestamp(struct AVFormatContext *s, int stream,\n                            int64_t *dts, int64_t *wall);\n\n\n/**\n * @}\n */\n\n\n/**\n * @defgroup lavf_misc Utility functions\n * @ingroup libavf\n * @{\n *\n * Miscellaneous utility functions related to both muxing and demuxing\n * (or neither).\n */\n\n/**\n * Send a nice hexadecimal dump of a buffer to the specified file stream.\n *\n * @param f The file stream pointer where the dump should be sent to.\n * @param buf buffer\n * @param size buffer size\n *\n * @see av_hex_dump_log, av_pkt_dump2, av_pkt_dump_log2\n */\nvoid av_hex_dump(FILE *f, const uint8_t *buf, int size);\n\n/**\n * Send a nice hexadecimal dump of a buffer to the log.\n *\n * @param avcl A pointer to an arbitrary struct of which the first field is a\n * pointer to an AVClass struct.\n * @param level The importance level of the message, lower values signifying\n * higher importance.\n * @param buf buffer\n * @param size buffer size\n *\n * @see av_hex_dump, av_pkt_dump2, av_pkt_dump_log2\n */\nvoid av_hex_dump_log(void *avcl, int level, const uint8_t *buf, int size);\n\n/**\n * Send a nice dump of a packet to the specified file stream.\n *\n * @param f The file stream pointer where the dump should be sent to.\n * @param pkt packet to dump\n * @param dump_payload True if the payload must be displayed, too.\n * @param st AVStream that the packet belongs to\n */\nvoid av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st);\n\n\n/**\n * Send a nice dump of a packet to the log.\n *\n * @param avcl A pointer to an arbitrary struct of which the first field is a\n * pointer to an AVClass struct.\n * @param level The importance level of the message, lower values signifying\n * higher importance.\n * @param pkt packet to dump\n * @param dump_payload True if the payload must be displayed, too.\n * @param st AVStream that the packet belongs to\n */\nvoid av_pkt_dump_log2(void *avcl, int level, const AVPacket *pkt, int dump_payload,\n                      const AVStream *st);\n\n/**\n * Get the AVCodecID for the given codec tag tag.\n * If no codec id is found returns AV_CODEC_ID_NONE.\n *\n * @param tags list of supported codec_id-codec_tag pairs, as stored\n * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag\n * @param tag  codec tag to match to a codec ID\n */\nenum AVCodecID av_codec_get_id(const struct AVCodecTag * const *tags, unsigned int tag);\n\n/**\n * Get the codec tag for the given codec id id.\n * If no codec tag is found returns 0.\n *\n * @param tags list of supported codec_id-codec_tag pairs, as stored\n * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag\n * @param id   codec ID to match to a codec tag\n */\nunsigned int av_codec_get_tag(const struct AVCodecTag * const *tags, enum AVCodecID id);\n\n/**\n * Get the codec tag for the given codec id.\n *\n * @param tags list of supported codec_id - codec_tag pairs, as stored\n * in AVInputFormat.codec_tag and AVOutputFormat.codec_tag\n * @param id codec id that should be searched for in the list\n * @param tag A pointer to the found tag\n * @return 0 if id was not found in tags, > 0 if it was found\n */\nint av_codec_get_tag2(const struct AVCodecTag * const *tags, enum AVCodecID id,\n                      unsigned int *tag);\n\nint av_find_default_stream_index(AVFormatContext *s);\n\n/**\n * Get the index for a specific timestamp.\n *\n * @param st        stream that the timestamp belongs to\n * @param timestamp timestamp to retrieve the index for\n * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond\n *                 to the timestamp which is <= the requested one, if backward\n *                 is 0, then it will be >=\n *              if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise\n * @return < 0 if no such timestamp could be found\n */\nint av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);\n\n/**\n * Get the index entry count for the given AVStream.\n *\n * @param st stream\n * @return the number of index entries in the stream\n */\nint avformat_index_get_entries_count(const AVStream *st);\n\n/**\n * Get the AVIndexEntry corresponding to the given index.\n *\n * @param st          Stream containing the requested AVIndexEntry.\n * @param idx         The desired index.\n * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise.\n *\n * @note The pointer returned by this function is only guaranteed to be valid\n *       until any function that takes the stream or the parent AVFormatContext\n *       as input argument is called.\n */\nconst AVIndexEntry *avformat_index_get_entry(AVStream *st, int idx);\n\n/**\n * Get the AVIndexEntry corresponding to the given timestamp.\n *\n * @param st          Stream containing the requested AVIndexEntry.\n * @param timestamp   Timestamp to retrieve the index entry for.\n * @param flags       If AVSEEK_FLAG_BACKWARD then the returned entry will correspond\n *                    to the timestamp which is <= the requested one, if backward\n *                    is 0, then it will be >=\n *                    if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise.\n * @return A pointer to the requested AVIndexEntry if it exists, NULL otherwise.\n *\n * @note The pointer returned by this function is only guaranteed to be valid\n *       until any function that takes the stream or the parent AVFormatContext\n *       as input argument is called.\n */\nconst AVIndexEntry *avformat_index_get_entry_from_timestamp(AVStream *st,\n                                                            int64_t wanted_timestamp,\n                                                            int flags);\n/**\n * Add an index entry into a sorted list. Update the entry if the list\n * already contains it.\n *\n * @param timestamp timestamp in the time base of the given stream\n */\nint av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,\n                       int size, int distance, int flags);\n\n\n/**\n * Split a URL string into components.\n *\n * The pointers to buffers for storing individual components may be null,\n * in order to ignore that component. Buffers for components not found are\n * set to empty strings. If the port is not found, it is set to a negative\n * value.\n *\n * @param proto the buffer for the protocol\n * @param proto_size the size of the proto buffer\n * @param authorization the buffer for the authorization\n * @param authorization_size the size of the authorization buffer\n * @param hostname the buffer for the host name\n * @param hostname_size the size of the hostname buffer\n * @param port_ptr a pointer to store the port number in\n * @param path the buffer for the path\n * @param path_size the size of the path buffer\n * @param url the URL to split\n */\nvoid av_url_split(char *proto,         int proto_size,\n                  char *authorization, int authorization_size,\n                  char *hostname,      int hostname_size,\n                  int *port_ptr,\n                  char *path,          int path_size,\n                  const char *url);\n\n\n/**\n * Print detailed information about the input or output format, such as\n * duration, bitrate, streams, container, programs, metadata, side data,\n * codec and time base.\n *\n * @param ic        the context to analyze\n * @param index     index of the stream to dump information about\n * @param url       the URL to print, such as source or destination file\n * @param is_output Select whether the specified context is an input(0) or output(1)\n */\nvoid av_dump_format(AVFormatContext *ic,\n                    int index,\n                    const char *url,\n                    int is_output);\n\n\n#define AV_FRAME_FILENAME_FLAGS_MULTIPLE 1 ///< Allow multiple %d\n\n/**\n * Return in 'buf' the path with '%d' replaced by a number.\n *\n * Also handles the '%0nd' format where 'n' is the total number\n * of digits and '%%'.\n *\n * @param buf destination buffer\n * @param buf_size destination buffer size\n * @param path numbered sequence string\n * @param number frame number\n * @param flags AV_FRAME_FILENAME_FLAGS_*\n * @return 0 if OK, -1 on format error\n */\nint av_get_frame_filename2(char *buf, int buf_size,\n                          const char *path, int number, int flags);\n\nint av_get_frame_filename(char *buf, int buf_size,\n                          const char *path, int number);\n\n/**\n * Check whether filename actually is a numbered sequence generator.\n *\n * @param filename possible numbered sequence string\n * @return 1 if a valid numbered sequence string, 0 otherwise\n */\nint av_filename_number_test(const char *filename);\n\n/**\n * Generate an SDP for an RTP session.\n *\n * Note, this overwrites the id values of AVStreams in the muxer contexts\n * for getting unique dynamic payload types.\n *\n * @param ac array of AVFormatContexts describing the RTP streams. If the\n *           array is composed by only one context, such context can contain\n *           multiple AVStreams (one AVStream per RTP stream). Otherwise,\n *           all the contexts in the array (an AVCodecContext per RTP stream)\n *           must contain only one AVStream.\n * @param n_files number of AVCodecContexts contained in ac\n * @param buf buffer where the SDP will be stored (must be allocated by\n *            the caller)\n * @param size the size of the buffer\n * @return 0 if OK, AVERROR_xxx on error\n */\nint av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size);\n\n/**\n * Return a positive value if the given filename has one of the given\n * extensions, 0 otherwise.\n *\n * @param filename   file name to check against the given extensions\n * @param extensions a comma-separated list of filename extensions\n */\nint av_match_ext(const char *filename, const char *extensions);\n\n/**\n * Test if the given container can store a codec.\n *\n * @param ofmt           container to check for compatibility\n * @param codec_id       codec to potentially store in container\n * @param std_compliance standards compliance level, one of FF_COMPLIANCE_*\n *\n * @return 1 if codec with ID codec_id can be stored in ofmt, 0 if it cannot.\n *         A negative number if this information is not available.\n */\nint avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,\n                         int std_compliance);\n\n/**\n * @defgroup riff_fourcc RIFF FourCCs\n * @{\n * Get the tables mapping RIFF FourCCs to libavcodec AVCodecIDs. The tables are\n * meant to be passed to av_codec_get_id()/av_codec_get_tag() as in the\n * following code:\n * @code\n * uint32_t tag = MKTAG('H', '2', '6', '4');\n * const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 };\n * enum AVCodecID id = av_codec_get_id(table, tag);\n * @endcode\n */\n/**\n * @return the table mapping RIFF FourCCs for video to libavcodec AVCodecID.\n */\nconst struct AVCodecTag *avformat_get_riff_video_tags(void);\n/**\n * @return the table mapping RIFF FourCCs for audio to AVCodecID.\n */\nconst struct AVCodecTag *avformat_get_riff_audio_tags(void);\n/**\n * @return the table mapping MOV FourCCs for video to libavcodec AVCodecID.\n */\nconst struct AVCodecTag *avformat_get_mov_video_tags(void);\n/**\n * @return the table mapping MOV FourCCs for audio to AVCodecID.\n */\nconst struct AVCodecTag *avformat_get_mov_audio_tags(void);\n\n/**\n * @}\n */\n\n/**\n * Guess the sample aspect ratio of a frame, based on both the stream and the\n * frame aspect ratio.\n *\n * Since the frame aspect ratio is set by the codec but the stream aspect ratio\n * is set by the demuxer, these two may not be equal. This function tries to\n * return the value that you should use if you would like to display the frame.\n *\n * Basic logic is to use the stream aspect ratio if it is set to something sane\n * otherwise use the frame aspect ratio. This way a container setting, which is\n * usually easy to modify can override the coded value in the frames.\n *\n * @param format the format context which the stream is part of\n * @param stream the stream which the frame is part of\n * @param frame the frame with the aspect ratio to be determined\n * @return the guessed (valid) sample_aspect_ratio, 0/1 if no idea\n */\nAVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame);\n\n/**\n * Guess the frame rate, based on both the container and codec information.\n *\n * @param ctx the format context which the stream is part of\n * @param stream the stream which the frame is part of\n * @param frame the frame for which the frame rate should be determined, may be NULL\n * @return the guessed (valid) frame rate, 0/1 if no idea\n */\nAVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame);\n\n/**\n * Check if the stream st contained in s is matched by the stream specifier\n * spec.\n *\n * See the \"stream specifiers\" chapter in the documentation for the syntax\n * of spec.\n *\n * @return  >0 if st is matched by spec;\n *          0  if st is not matched by spec;\n *          AVERROR code if spec is invalid\n *\n * @note  A stream specifier can match several streams in the format.\n */\nint avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,\n                                    const char *spec);\n\nint avformat_queue_attached_pictures(AVFormatContext *s);\n\nenum AVTimebaseSource {\n    AVFMT_TBCF_AUTO = -1,\n    AVFMT_TBCF_DECODER,\n    AVFMT_TBCF_DEMUXER,\n#if FF_API_R_FRAME_RATE\n    AVFMT_TBCF_R_FRAMERATE,\n#endif\n};\n\n/**\n * Transfer internal timing information from one stream to another.\n *\n * This function is useful when doing stream copy.\n *\n * @param ofmt     target output format for ost\n * @param ost      output stream which needs timings copy and adjustments\n * @param ist      reference input stream to copy timings from\n * @param copy_tb  define from where the stream codec timebase needs to be imported\n */\nint avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,\n                                                  AVStream *ost, const AVStream *ist,\n                                                  enum AVTimebaseSource copy_tb);\n\n/**\n * Get the internal codec timebase from a stream.\n *\n * @param st  input stream to extract the timebase from\n */\nAVRational av_stream_get_codec_timebase(const AVStream *st);\n\n/**\n * @}\n */\n\n#endif /* AVFORMAT_AVFORMAT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavformat/avio.h",
    "content": "/*\n * copyright (c) 2001 Fabrice Bellard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n#ifndef AVFORMAT_AVIO_H\n#define AVFORMAT_AVIO_H\n\n/**\n * @file\n * @ingroup lavf_io\n * Buffered I/O operations\n */\n\n#include <stdint.h>\n#include <stdio.h>\n\n#include \"libavutil/attributes.h\"\n#include \"libavutil/dict.h\"\n#include \"libavutil/log.h\"\n\n#include \"libavformat/version_major.h\"\n\n/**\n * Seeking works like for a local file.\n */\n#define AVIO_SEEKABLE_NORMAL (1 << 0)\n\n/**\n * Seeking by timestamp with avio_seek_time() is possible.\n */\n#define AVIO_SEEKABLE_TIME   (1 << 1)\n\n/**\n * Callback for checking whether to abort blocking functions.\n * AVERROR_EXIT is returned in this case by the interrupted\n * function. During blocking operations, callback is called with\n * opaque as parameter. If the callback returns 1, the\n * blocking operation will be aborted.\n *\n * No members can be added to this struct without a major bump, if\n * new elements have been added after this struct in AVFormatContext\n * or AVIOContext.\n */\ntypedef struct AVIOInterruptCB {\n    int (*callback)(void*);\n    void *opaque;\n} AVIOInterruptCB;\n\n/**\n * Directory entry types.\n */\nenum AVIODirEntryType {\n    AVIO_ENTRY_UNKNOWN,\n    AVIO_ENTRY_BLOCK_DEVICE,\n    AVIO_ENTRY_CHARACTER_DEVICE,\n    AVIO_ENTRY_DIRECTORY,\n    AVIO_ENTRY_NAMED_PIPE,\n    AVIO_ENTRY_SYMBOLIC_LINK,\n    AVIO_ENTRY_SOCKET,\n    AVIO_ENTRY_FILE,\n    AVIO_ENTRY_SERVER,\n    AVIO_ENTRY_SHARE,\n    AVIO_ENTRY_WORKGROUP,\n};\n\n/**\n * Describes single entry of the directory.\n *\n * Only name and type fields are guaranteed be set.\n * Rest of fields are protocol or/and platform dependent and might be unknown.\n */\ntypedef struct AVIODirEntry {\n    char *name;                           /**< Filename */\n    int type;                             /**< Type of the entry */\n    int utf8;                             /**< Set to 1 when name is encoded with UTF-8, 0 otherwise.\n                                               Name can be encoded with UTF-8 even though 0 is set. */\n    int64_t size;                         /**< File size in bytes, -1 if unknown. */\n    int64_t modification_timestamp;       /**< Time of last modification in microseconds since unix\n                                               epoch, -1 if unknown. */\n    int64_t access_timestamp;             /**< Time of last access in microseconds since unix epoch,\n                                               -1 if unknown. */\n    int64_t status_change_timestamp;      /**< Time of last status change in microseconds since unix\n                                               epoch, -1 if unknown. */\n    int64_t user_id;                      /**< User ID of owner, -1 if unknown. */\n    int64_t group_id;                     /**< Group ID of owner, -1 if unknown. */\n    int64_t filemode;                     /**< Unix file mode, -1 if unknown. */\n} AVIODirEntry;\n\ntypedef struct AVIODirContext {\n    struct URLContext *url_context;\n} AVIODirContext;\n\n/**\n * Different data types that can be returned via the AVIO\n * write_data_type callback.\n */\nenum AVIODataMarkerType {\n    /**\n     * Header data; this needs to be present for the stream to be decodeable.\n     */\n    AVIO_DATA_MARKER_HEADER,\n    /**\n     * A point in the output bytestream where a decoder can start decoding\n     * (i.e. a keyframe). A demuxer/decoder given the data flagged with\n     * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT,\n     * should give decodeable results.\n     */\n    AVIO_DATA_MARKER_SYNC_POINT,\n    /**\n     * A point in the output bytestream where a demuxer can start parsing\n     * (for non self synchronizing bytestream formats). That is, any\n     * non-keyframe packet start point.\n     */\n    AVIO_DATA_MARKER_BOUNDARY_POINT,\n    /**\n     * This is any, unlabelled data. It can either be a muxer not marking\n     * any positions at all, it can be an actual boundary/sync point\n     * that the muxer chooses not to mark, or a later part of a packet/fragment\n     * that is cut into multiple write callbacks due to limited IO buffer size.\n     */\n    AVIO_DATA_MARKER_UNKNOWN,\n    /**\n     * Trailer data, which doesn't contain actual content, but only for\n     * finalizing the output file.\n     */\n    AVIO_DATA_MARKER_TRAILER,\n    /**\n     * A point in the output bytestream where the underlying AVIOContext might\n     * flush the buffer depending on latency or buffering requirements. Typically\n     * means the end of a packet.\n     */\n    AVIO_DATA_MARKER_FLUSH_POINT,\n};\n\n/**\n * Bytestream IO Context.\n * New public fields can be added with minor version bumps.\n * Removal, reordering and changes to existing public fields require\n * a major version bump.\n * sizeof(AVIOContext) must not be used outside libav*.\n *\n * @note None of the function pointers in AVIOContext should be called\n *       directly, they should only be set by the client application\n *       when implementing custom I/O. Normally these are set to the\n *       function pointers specified in avio_alloc_context()\n */\ntypedef struct AVIOContext {\n    /**\n     * A class for private options.\n     *\n     * If this AVIOContext is created by avio_open2(), av_class is set and\n     * passes the options down to protocols.\n     *\n     * If this AVIOContext is manually allocated, then av_class may be set by\n     * the caller.\n     *\n     * warning -- this field can be NULL, be sure to not pass this AVIOContext\n     * to any av_opt_* functions in that case.\n     */\n    const AVClass *av_class;\n\n    /*\n     * The following shows the relationship between buffer, buf_ptr,\n     * buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing\n     * (since AVIOContext is used for both):\n     *\n     **********************************************************************************\n     *                                   READING\n     **********************************************************************************\n     *\n     *                            |              buffer_size              |\n     *                            |---------------------------------------|\n     *                            |                                       |\n     *\n     *                         buffer          buf_ptr       buf_end\n     *                            +---------------+-----------------------+\n     *                            |/ / / / / / / /|/ / / / / / /|         |\n     *  read buffer:              |/ / consumed / | to be read /|         |\n     *                            |/ / / / / / / /|/ / / / / / /|         |\n     *                            +---------------+-----------------------+\n     *\n     *                                                         pos\n     *              +-------------------------------------------+-----------------+\n     *  input file: |                                           |                 |\n     *              +-------------------------------------------+-----------------+\n     *\n     *\n     **********************************************************************************\n     *                                   WRITING\n     **********************************************************************************\n     *\n     *                             |          buffer_size                 |\n     *                             |--------------------------------------|\n     *                             |                                      |\n     *\n     *                                                buf_ptr_max\n     *                          buffer                 (buf_ptr)       buf_end\n     *                             +-----------------------+--------------+\n     *                             |/ / / / / / / / / / / /|              |\n     *  write buffer:              | / / to be flushed / / |              |\n     *                             |/ / / / / / / / / / / /|              |\n     *                             +-----------------------+--------------+\n     *                               buf_ptr can be in this\n     *                               due to a backward seek\n     *\n     *                            pos\n     *               +-------------+----------------------------------------------+\n     *  output file: |             |                                              |\n     *               +-------------+----------------------------------------------+\n     *\n     */\n    unsigned char *buffer;  /**< Start of the buffer. */\n    int buffer_size;        /**< Maximum buffer size */\n    unsigned char *buf_ptr; /**< Current position in the buffer */\n    unsigned char *buf_end; /**< End of the data, may be less than\n                                 buffer+buffer_size if the read function returned\n                                 less data than requested, e.g. for streams where\n                                 no more data has been received yet. */\n    void *opaque;           /**< A private pointer, passed to the read/write/seek/...\n                                 functions. */\n    int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);\n    int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);\n    int64_t (*seek)(void *opaque, int64_t offset, int whence);\n    int64_t pos;            /**< position in the file of the current buffer */\n    int eof_reached;        /**< true if was unable to read due to error or eof */\n    int error;              /**< contains the error code or 0 if no error happened */\n    int write_flag;         /**< true if open for writing */\n    int max_packet_size;\n    int min_packet_size;    /**< Try to buffer at least this amount of data\n                                 before flushing it. */\n    unsigned long checksum;\n    unsigned char *checksum_ptr;\n    unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);\n    /**\n     * Pause or resume playback for network streaming protocols - e.g. MMS.\n     */\n    int (*read_pause)(void *opaque, int pause);\n    /**\n     * Seek to a given timestamp in stream with the specified stream_index.\n     * Needed for some network streaming protocols which don't support seeking\n     * to byte position.\n     */\n    int64_t (*read_seek)(void *opaque, int stream_index,\n                         int64_t timestamp, int flags);\n    /**\n     * A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.\n     */\n    int seekable;\n\n    /**\n     * avio_read and avio_write should if possible be satisfied directly\n     * instead of going through a buffer, and avio_seek will always\n     * call the underlying seek function directly.\n     */\n    int direct;\n\n    /**\n     * ',' separated list of allowed protocols.\n     */\n    const char *protocol_whitelist;\n\n    /**\n     * ',' separated list of disallowed protocols.\n     */\n    const char *protocol_blacklist;\n\n    /**\n     * A callback that is used instead of write_packet.\n     */\n    int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,\n                           enum AVIODataMarkerType type, int64_t time);\n    /**\n     * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT,\n     * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly\n     * small chunks of data returned from the callback).\n     */\n    int ignore_boundary_point;\n\n#if FF_API_AVIOCONTEXT_WRITTEN\n    /**\n     * @deprecated field utilized privately by libavformat. For a public\n     *             statistic of how many bytes were written out, see\n     *             AVIOContext::bytes_written.\n     */\n    attribute_deprecated\n    int64_t written;\n#endif\n\n    /**\n     * Maximum reached position before a backward seek in the write buffer,\n     * used keeping track of already written data for a later flush.\n     */\n    unsigned char *buf_ptr_max;\n\n    /**\n     * Read-only statistic of bytes read for this AVIOContext.\n     */\n    int64_t bytes_read;\n\n    /**\n     * Read-only statistic of bytes written for this AVIOContext.\n     */\n    int64_t bytes_written;\n} AVIOContext;\n\n/**\n * Return the name of the protocol that will handle the passed URL.\n *\n * NULL is returned if no protocol could be found for the given URL.\n *\n * @return Name of the protocol or NULL.\n */\nconst char *avio_find_protocol_name(const char *url);\n\n/**\n * Return AVIO_FLAG_* access flags corresponding to the access permissions\n * of the resource in url, or a negative value corresponding to an\n * AVERROR code in case of failure. The returned access flags are\n * masked by the value in flags.\n *\n * @note This function is intrinsically unsafe, in the sense that the\n * checked resource may change its existence or permission status from\n * one call to another. Thus you should not trust the returned value,\n * unless you are sure that no other processes are accessing the\n * checked resource.\n */\nint avio_check(const char *url, int flags);\n\n/**\n * Open directory for reading.\n *\n * @param s       directory read context. Pointer to a NULL pointer must be passed.\n * @param url     directory to be listed.\n * @param options A dictionary filled with protocol-private options. On return\n *                this parameter will be destroyed and replaced with a dictionary\n *                containing options that were not found. May be NULL.\n * @return >=0 on success or negative on error.\n */\nint avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options);\n\n/**\n * Get next directory entry.\n *\n * Returned entry must be freed with avio_free_directory_entry(). In particular\n * it may outlive AVIODirContext.\n *\n * @param s         directory read context.\n * @param[out] next next entry or NULL when no more entries.\n * @return >=0 on success or negative on error. End of list is not considered an\n *             error.\n */\nint avio_read_dir(AVIODirContext *s, AVIODirEntry **next);\n\n/**\n * Close directory.\n *\n * @note Entries created using avio_read_dir() are not deleted and must be\n * freeded with avio_free_directory_entry().\n *\n * @param s         directory read context.\n * @return >=0 on success or negative on error.\n */\nint avio_close_dir(AVIODirContext **s);\n\n/**\n * Free entry allocated by avio_read_dir().\n *\n * @param entry entry to be freed.\n */\nvoid avio_free_directory_entry(AVIODirEntry **entry);\n\n/**\n * Allocate and initialize an AVIOContext for buffered I/O. It must be later\n * freed with avio_context_free().\n *\n * @param buffer Memory block for input/output operations via AVIOContext.\n *        The buffer must be allocated with av_malloc() and friends.\n *        It may be freed and replaced with a new buffer by libavformat.\n *        AVIOContext.buffer holds the buffer currently in use,\n *        which must be later freed with av_free().\n * @param buffer_size The buffer size is very important for performance.\n *        For protocols with fixed blocksize it should be set to this blocksize.\n *        For others a typical size is a cache page, e.g. 4kb.\n * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise.\n * @param opaque An opaque pointer to user-specific data.\n * @param read_packet  A function for refilling the buffer, may be NULL.\n *                     For stream protocols, must never return 0 but rather\n *                     a proper AVERROR code.\n * @param write_packet A function for writing the buffer contents, may be NULL.\n *        The function may not change the input buffers content.\n * @param seek A function for seeking to specified byte position, may be NULL.\n *\n * @return Allocated AVIOContext or NULL on failure.\n */\nAVIOContext *avio_alloc_context(\n                  unsigned char *buffer,\n                  int buffer_size,\n                  int write_flag,\n                  void *opaque,\n                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),\n                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),\n                  int64_t (*seek)(void *opaque, int64_t offset, int whence));\n\n/**\n * Free the supplied IO context and everything associated with it.\n *\n * @param s Double pointer to the IO context. This function will write NULL\n * into s.\n */\nvoid avio_context_free(AVIOContext **s);\n\nvoid avio_w8(AVIOContext *s, int b);\nvoid avio_write(AVIOContext *s, const unsigned char *buf, int size);\nvoid avio_wl64(AVIOContext *s, uint64_t val);\nvoid avio_wb64(AVIOContext *s, uint64_t val);\nvoid avio_wl32(AVIOContext *s, unsigned int val);\nvoid avio_wb32(AVIOContext *s, unsigned int val);\nvoid avio_wl24(AVIOContext *s, unsigned int val);\nvoid avio_wb24(AVIOContext *s, unsigned int val);\nvoid avio_wl16(AVIOContext *s, unsigned int val);\nvoid avio_wb16(AVIOContext *s, unsigned int val);\n\n/**\n * Write a NULL-terminated string.\n * @return number of bytes written.\n */\nint avio_put_str(AVIOContext *s, const char *str);\n\n/**\n * Convert an UTF-8 string to UTF-16LE and write it.\n * @param s the AVIOContext\n * @param str NULL-terminated UTF-8 string\n *\n * @return number of bytes written.\n */\nint avio_put_str16le(AVIOContext *s, const char *str);\n\n/**\n * Convert an UTF-8 string to UTF-16BE and write it.\n * @param s the AVIOContext\n * @param str NULL-terminated UTF-8 string\n *\n * @return number of bytes written.\n */\nint avio_put_str16be(AVIOContext *s, const char *str);\n\n/**\n * Mark the written bytestream as a specific type.\n *\n * Zero-length ranges are omitted from the output.\n *\n * @param time the stream time the current bytestream pos corresponds to\n *             (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not\n *             applicable\n * @param type the kind of data written starting at the current pos\n */\nvoid avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type);\n\n/**\n * ORing this as the \"whence\" parameter to a seek function causes it to\n * return the filesize without seeking anywhere. Supporting this is optional.\n * If it is not supported then the seek function will return <0.\n */\n#define AVSEEK_SIZE 0x10000\n\n/**\n * Passing this flag as the \"whence\" parameter to a seek function causes it to\n * seek by any means (like reopening and linear reading) or other normally unreasonable\n * means that can be extremely slow.\n * This may be ignored by the seek code.\n */\n#define AVSEEK_FORCE 0x20000\n\n/**\n * fseek() equivalent for AVIOContext.\n * @return new position or AVERROR.\n */\nint64_t avio_seek(AVIOContext *s, int64_t offset, int whence);\n\n/**\n * Skip given number of bytes forward\n * @return new position or AVERROR.\n */\nint64_t avio_skip(AVIOContext *s, int64_t offset);\n\n/**\n * ftell() equivalent for AVIOContext.\n * @return position or AVERROR.\n */\nstatic av_always_inline int64_t avio_tell(AVIOContext *s)\n{\n    return avio_seek(s, 0, SEEK_CUR);\n}\n\n/**\n * Get the filesize.\n * @return filesize or AVERROR\n */\nint64_t avio_size(AVIOContext *s);\n\n/**\n * Similar to feof() but also returns nonzero on read errors.\n * @return non zero if and only if at end of file or a read error happened when reading.\n */\nint avio_feof(AVIOContext *s);\n\n/**\n * Writes a formatted string to the context taking a va_list.\n * @return number of bytes written, < 0 on error.\n */\nint avio_vprintf(AVIOContext *s, const char *fmt, va_list ap);\n\n/**\n * Writes a formatted string to the context.\n * @return number of bytes written, < 0 on error.\n */\nint avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3);\n\n/**\n * Write a NULL terminated array of strings to the context.\n * Usually you don't need to use this function directly but its macro wrapper,\n * avio_print.\n */\nvoid avio_print_string_array(AVIOContext *s, const char *strings[]);\n\n/**\n * Write strings (const char *) to the context.\n * This is a convenience macro around avio_print_string_array and it\n * automatically creates the string array from the variable argument list.\n * For simple string concatenations this function is more performant than using\n * avio_printf since it does not need a temporary buffer.\n */\n#define avio_print(s, ...) \\\n    avio_print_string_array(s, (const char*[]){__VA_ARGS__, NULL})\n\n/**\n * Force flushing of buffered data.\n *\n * For write streams, force the buffered data to be immediately written to the output,\n * without to wait to fill the internal buffer.\n *\n * For read streams, discard all currently buffered data, and advance the\n * reported file position to that of the underlying stream. This does not\n * read new data, and does not perform any seeks.\n */\nvoid avio_flush(AVIOContext *s);\n\n/**\n * Read size bytes from AVIOContext into buf.\n * @return number of bytes read or AVERROR\n */\nint avio_read(AVIOContext *s, unsigned char *buf, int size);\n\n/**\n * Read size bytes from AVIOContext into buf. Unlike avio_read(), this is allowed\n * to read fewer bytes than requested. The missing bytes can be read in the next\n * call. This always tries to read at least 1 byte.\n * Useful to reduce latency in certain cases.\n * @return number of bytes read or AVERROR\n */\nint avio_read_partial(AVIOContext *s, unsigned char *buf, int size);\n\n/**\n * @name Functions for reading from AVIOContext\n * @{\n *\n * @note return 0 if EOF, so you cannot use it if EOF handling is\n *       necessary\n */\nint          avio_r8  (AVIOContext *s);\nunsigned int avio_rl16(AVIOContext *s);\nunsigned int avio_rl24(AVIOContext *s);\nunsigned int avio_rl32(AVIOContext *s);\nuint64_t     avio_rl64(AVIOContext *s);\nunsigned int avio_rb16(AVIOContext *s);\nunsigned int avio_rb24(AVIOContext *s);\nunsigned int avio_rb32(AVIOContext *s);\nuint64_t     avio_rb64(AVIOContext *s);\n/**\n * @}\n */\n\n/**\n * Read a string from pb into buf. The reading will terminate when either\n * a NULL character was encountered, maxlen bytes have been read, or nothing\n * more can be read from pb. The result is guaranteed to be NULL-terminated, it\n * will be truncated if buf is too small.\n * Note that the string is not interpreted or validated in any way, it\n * might get truncated in the middle of a sequence for multi-byte encodings.\n *\n * @return number of bytes read (is always <= maxlen).\n * If reading ends on EOF or error, the return value will be one more than\n * bytes actually read.\n */\nint avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen);\n\n/**\n * Read a UTF-16 string from pb and convert it to UTF-8.\n * The reading will terminate when either a null or invalid character was\n * encountered or maxlen bytes have been read.\n * @return number of bytes read (is always <= maxlen)\n */\nint avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen);\nint avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen);\n\n\n/**\n * @name URL open modes\n * The flags argument to avio_open must be one of the following\n * constants, optionally ORed with other flags.\n * @{\n */\n#define AVIO_FLAG_READ  1                                      /**< read-only */\n#define AVIO_FLAG_WRITE 2                                      /**< write-only */\n#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE)  /**< read-write pseudo flag */\n/**\n * @}\n */\n\n/**\n * Use non-blocking mode.\n * If this flag is set, operations on the context will return\n * AVERROR(EAGAIN) if they can not be performed immediately.\n * If this flag is not set, operations on the context will never return\n * AVERROR(EAGAIN).\n * Note that this flag does not affect the opening/connecting of the\n * context. Connecting a protocol will always block if necessary (e.g. on\n * network protocols) but never hang (e.g. on busy devices).\n * Warning: non-blocking protocols is work-in-progress; this flag may be\n * silently ignored.\n */\n#define AVIO_FLAG_NONBLOCK 8\n\n/**\n * Use direct mode.\n * avio_read and avio_write should if possible be satisfied directly\n * instead of going through a buffer, and avio_seek will always\n * call the underlying seek function directly.\n */\n#define AVIO_FLAG_DIRECT 0x8000\n\n/**\n * Create and initialize a AVIOContext for accessing the\n * resource indicated by url.\n * @note When the resource indicated by url has been opened in\n * read+write mode, the AVIOContext can be used only for writing.\n *\n * @param s Used to return the pointer to the created AVIOContext.\n * In case of failure the pointed to value is set to NULL.\n * @param url resource to access\n * @param flags flags which control how the resource indicated by url\n * is to be opened\n * @return >= 0 in case of success, a negative value corresponding to an\n * AVERROR code in case of failure\n */\nint avio_open(AVIOContext **s, const char *url, int flags);\n\n/**\n * Create and initialize a AVIOContext for accessing the\n * resource indicated by url.\n * @note When the resource indicated by url has been opened in\n * read+write mode, the AVIOContext can be used only for writing.\n *\n * @param s Used to return the pointer to the created AVIOContext.\n * In case of failure the pointed to value is set to NULL.\n * @param url resource to access\n * @param flags flags which control how the resource indicated by url\n * is to be opened\n * @param int_cb an interrupt callback to be used at the protocols level\n * @param options  A dictionary filled with protocol-private options. On return\n * this parameter will be destroyed and replaced with a dict containing options\n * that were not found. May be NULL.\n * @return >= 0 in case of success, a negative value corresponding to an\n * AVERROR code in case of failure\n */\nint avio_open2(AVIOContext **s, const char *url, int flags,\n               const AVIOInterruptCB *int_cb, AVDictionary **options);\n\n/**\n * Close the resource accessed by the AVIOContext s and free it.\n * This function can only be used if s was opened by avio_open().\n *\n * The internal buffer is automatically flushed before closing the\n * resource.\n *\n * @return 0 on success, an AVERROR < 0 on error.\n * @see avio_closep\n */\nint avio_close(AVIOContext *s);\n\n/**\n * Close the resource accessed by the AVIOContext *s, free it\n * and set the pointer pointing to it to NULL.\n * This function can only be used if s was opened by avio_open().\n *\n * The internal buffer is automatically flushed before closing the\n * resource.\n *\n * @return 0 on success, an AVERROR < 0 on error.\n * @see avio_close\n */\nint avio_closep(AVIOContext **s);\n\n\n/**\n * Open a write only memory stream.\n *\n * @param s new IO context\n * @return zero if no error.\n */\nint avio_open_dyn_buf(AVIOContext **s);\n\n/**\n * Return the written size and a pointer to the buffer.\n * The AVIOContext stream is left intact.\n * The buffer must NOT be freed.\n * No padding is added to the buffer.\n *\n * @param s IO context\n * @param pbuffer pointer to a byte buffer\n * @return the length of the byte buffer\n */\nint avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer);\n\n/**\n * Return the written size and a pointer to the buffer. The buffer\n * must be freed with av_free().\n * Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer.\n *\n * @param s IO context\n * @param pbuffer pointer to a byte buffer\n * @return the length of the byte buffer\n */\nint avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer);\n\n/**\n * Iterate through names of available protocols.\n *\n * @param opaque A private pointer representing current protocol.\n *        It must be a pointer to NULL on first iteration and will\n *        be updated by successive calls to avio_enum_protocols.\n * @param output If set to 1, iterate over output protocols,\n *               otherwise over input protocols.\n *\n * @return A static string containing the name of current protocol or NULL\n */\nconst char *avio_enum_protocols(void **opaque, int output);\n\n/**\n * Get AVClass by names of available protocols.\n *\n * @return A AVClass of input protocol name or NULL\n */\nconst AVClass *avio_protocol_get_class(const char *name);\n\n/**\n * Pause and resume playing - only meaningful if using a network streaming\n * protocol (e.g. MMS).\n *\n * @param h     IO context from which to call the read_pause function pointer\n * @param pause 1 for pause, 0 for resume\n */\nint     avio_pause(AVIOContext *h, int pause);\n\n/**\n * Seek to a given timestamp relative to some component stream.\n * Only meaningful if using a network streaming protocol (e.g. MMS.).\n *\n * @param h IO context from which to call the seek function pointers\n * @param stream_index The stream index that the timestamp is relative to.\n *        If stream_index is (-1) the timestamp should be in AV_TIME_BASE\n *        units from the beginning of the presentation.\n *        If a stream_index >= 0 is used and the protocol does not support\n *        seeking based on component streams, the call will fail.\n * @param timestamp timestamp in AVStream.time_base units\n *        or if there is no stream specified then in AV_TIME_BASE units.\n * @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE\n *        and AVSEEK_FLAG_ANY. The protocol may silently ignore\n *        AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will\n *        fail if used and not supported.\n * @return >= 0 on success\n * @see AVInputFormat::read_seek\n */\nint64_t avio_seek_time(AVIOContext *h, int stream_index,\n                       int64_t timestamp, int flags);\n\n/* Avoid a warning. The header can not be included because it breaks c++. */\nstruct AVBPrint;\n\n/**\n * Read contents of h into print buffer, up to max_size bytes, or up to EOF.\n *\n * @return 0 for success (max_size bytes read or EOF reached), negative error\n * code otherwise\n */\nint avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size);\n\n/**\n * Accept and allocate a client context on a server context.\n * @param  s the server context\n * @param  c the client context, must be unallocated\n * @return   >= 0 on success or a negative value corresponding\n *           to an AVERROR on failure\n */\nint avio_accept(AVIOContext *s, AVIOContext **c);\n\n/**\n * Perform one step of the protocol handshake to accept a new client.\n * This function must be called on a client returned by avio_accept() before\n * using it as a read/write context.\n * It is separate from avio_accept() because it may block.\n * A step of the handshake is defined by places where the application may\n * decide to change the proceedings.\n * For example, on a protocol with a request header and a reply header, each\n * one can constitute a step because the application may use the parameters\n * from the request to change parameters in the reply; or each individual\n * chunk of the request can constitute a step.\n * If the handshake is already finished, avio_handshake() does nothing and\n * returns 0 immediately.\n *\n * @param  c the client context to perform the handshake on\n * @return   0   on a complete and successful handshake\n *           > 0 if the handshake progressed, but is not complete\n *           < 0 for an AVERROR code\n */\nint avio_handshake(AVIOContext *c);\n#endif /* AVFORMAT_AVIO_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavformat/version.h",
    "content": "/*\n * Version macros.\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVFORMAT_VERSION_H\n#define AVFORMAT_VERSION_H\n\n/**\n * @file\n * @ingroup libavf\n * Libavformat version macros\n */\n\n#include \"libavutil/version.h\"\n\n#include \"version_major.h\"\n\n#define LIBAVFORMAT_VERSION_MINOR  27\n#define LIBAVFORMAT_VERSION_MICRO 100\n\n#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \\\n                                               LIBAVFORMAT_VERSION_MINOR, \\\n                                               LIBAVFORMAT_VERSION_MICRO)\n#define LIBAVFORMAT_VERSION     AV_VERSION(LIBAVFORMAT_VERSION_MAJOR,   \\\n                                           LIBAVFORMAT_VERSION_MINOR,   \\\n                                           LIBAVFORMAT_VERSION_MICRO)\n#define LIBAVFORMAT_BUILD       LIBAVFORMAT_VERSION_INT\n\n#define LIBAVFORMAT_IDENT       \"Lavf\" AV_STRINGIFY(LIBAVFORMAT_VERSION)\n\n#endif /* AVFORMAT_VERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavformat/version_major.h",
    "content": "/*\n * Version macros.\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVFORMAT_VERSION_MAJOR_H\n#define AVFORMAT_VERSION_MAJOR_H\n\n/**\n * @file\n * @ingroup libavf\n * Libavformat version macros\n */\n\n// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)\n// Also please add any ticket numbers that you believe might be affected here\n#define LIBAVFORMAT_VERSION_MAJOR  59\n\n/**\n * FF_API_* defines may be placed below to indicate public API that will be\n * dropped at a future version bump. The defines themselves are not part of\n * the public API and may change, break or disappear at any time.\n *\n * @note, when bumping the major version it is recommended to manually\n * disable each FF_API_* in its own commit instead of disabling them all\n * at once through the bump. This improves the git bisect-ability of the change.\n *\n */\n#define FF_API_LAVF_PRIV_OPT            (LIBAVFORMAT_VERSION_MAJOR < 60)\n#define FF_API_COMPUTE_PKT_FIELDS2      (LIBAVFORMAT_VERSION_MAJOR < 60)\n#define FF_API_AVIOCONTEXT_WRITTEN      (LIBAVFORMAT_VERSION_MAJOR < 60)\n#define FF_HLS_TS_OPTIONS               (LIBAVFORMAT_VERSION_MAJOR < 60)\n#define FF_API_AVSTREAM_CLASS           (LIBAVFORMAT_VERSION_MAJOR > 59)\n\n\n#define FF_API_R_FRAME_RATE            1\n\n#endif /* AVFORMAT_VERSION_MAJOR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/adler32.h",
    "content": "/*\n * copyright (c) 2006 Mans Rullgard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_adler32\n * Public header for Adler-32 hash function implementation.\n */\n\n#ifndef AVUTIL_ADLER32_H\n#define AVUTIL_ADLER32_H\n\n#include <stddef.h>\n#include <stdint.h>\n#include \"attributes.h\"\n\n/**\n * @defgroup lavu_adler32 Adler-32\n * @ingroup lavu_hash\n * Adler-32 hash function implementation.\n *\n * @{\n */\n\ntypedef uint32_t AVAdler;\n\n/**\n * Calculate the Adler32 checksum of a buffer.\n *\n * Passing the return value to a subsequent av_adler32_update() call\n * allows the checksum of multiple buffers to be calculated as though\n * they were concatenated.\n *\n * @param adler initial checksum value\n * @param buf   pointer to input buffer\n * @param len   size of input buffer\n * @return      updated checksum\n */\nAVAdler av_adler32_update(AVAdler adler, const uint8_t *buf,\n                          size_t len) av_pure;\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_ADLER32_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/aes.h",
    "content": "/*\n * copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_AES_H\n#define AVUTIL_AES_H\n\n#include <stdint.h>\n\n#include \"attributes.h\"\n\n/**\n * @defgroup lavu_aes AES\n * @ingroup lavu_crypto\n * @{\n */\n\nextern const int av_aes_size;\n\nstruct AVAES;\n\n/**\n * Allocate an AVAES context.\n */\nstruct AVAES *av_aes_alloc(void);\n\n/**\n * Initialize an AVAES context.\n * @param key_bits 128, 192 or 256\n * @param decrypt 0 for encryption, 1 for decryption\n */\nint av_aes_init(struct AVAES *a, const uint8_t *key, int key_bits, int decrypt);\n\n/**\n * Encrypt or decrypt a buffer using a previously initialized context.\n * @param count number of 16 byte blocks\n * @param dst destination array, can be equal to src\n * @param src source array, can be equal to dst\n * @param iv initialization vector for CBC mode, if NULL then ECB will be used\n * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_aes_crypt(struct AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_AES_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/aes_ctr.h",
    "content": "/*\n * AES-CTR cipher\n * Copyright (c) 2015 Eran Kornblau <erankor at gmail dot com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_AES_CTR_H\n#define AVUTIL_AES_CTR_H\n\n#include <stdint.h>\n\n#include \"attributes.h\"\n\n#define AES_CTR_KEY_SIZE (16)\n#define AES_CTR_IV_SIZE (8)\n\nstruct AVAESCTR;\n\n/**\n * Allocate an AVAESCTR context.\n */\nstruct AVAESCTR *av_aes_ctr_alloc(void);\n\n/**\n * Initialize an AVAESCTR context.\n * @param key encryption key, must have a length of AES_CTR_KEY_SIZE\n */\nint av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key);\n\n/**\n * Release an AVAESCTR context.\n */\nvoid av_aes_ctr_free(struct AVAESCTR *a);\n\n/**\n * Process a buffer using a previously initialized context.\n * @param dst destination array, can be equal to src\n * @param src source array, can be equal to dst\n * @param size the size of src and dst\n */\nvoid av_aes_ctr_crypt(struct AVAESCTR *a, uint8_t *dst, const uint8_t *src, int size);\n\n/**\n * Get the current iv\n */\nconst uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a);\n\n/**\n * Generate a random iv\n */\nvoid av_aes_ctr_set_random_iv(struct AVAESCTR *a);\n\n/**\n * Forcefully change the 8-byte iv\n */\nvoid av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv);\n\n/**\n * Forcefully change the \"full\" 16-byte iv, including the counter\n */\nvoid av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv);\n\n/**\n * Increment the top 64 bit of the iv (performed after each frame)\n */\nvoid av_aes_ctr_increment_iv(struct AVAESCTR *a);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_AES_CTR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/attributes.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * Macro definitions for various function/variable attributes\n */\n\n#ifndef AVUTIL_ATTRIBUTES_H\n#define AVUTIL_ATTRIBUTES_H\n\n#ifdef __GNUC__\n#    define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))\n#    define AV_GCC_VERSION_AT_MOST(x,y)  (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y))\n#else\n#    define AV_GCC_VERSION_AT_LEAST(x,y) 0\n#    define AV_GCC_VERSION_AT_MOST(x,y)  0\n#endif\n\n#ifdef __has_builtin\n#    define AV_HAS_BUILTIN(x) __has_builtin(x)\n#else\n#    define AV_HAS_BUILTIN(x) 0\n#endif\n\n#ifndef av_always_inline\n#if AV_GCC_VERSION_AT_LEAST(3,1)\n#    define av_always_inline __attribute__((always_inline)) inline\n#elif defined(_MSC_VER)\n#    define av_always_inline __forceinline\n#else\n#    define av_always_inline inline\n#endif\n#endif\n\n#ifndef av_extern_inline\n#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__)\n#    define av_extern_inline extern inline\n#else\n#    define av_extern_inline inline\n#endif\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(3,4)\n#    define av_warn_unused_result __attribute__((warn_unused_result))\n#else\n#    define av_warn_unused_result\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(3,1)\n#    define av_noinline __attribute__((noinline))\n#elif defined(_MSC_VER)\n#    define av_noinline __declspec(noinline)\n#else\n#    define av_noinline\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__)\n#    define av_pure __attribute__((pure))\n#else\n#    define av_pure\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__)\n#    define av_const __attribute__((const))\n#else\n#    define av_const\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__)\n#    define av_cold __attribute__((cold))\n#else\n#    define av_cold\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__)\n#    define av_flatten __attribute__((flatten))\n#else\n#    define av_flatten\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(3,1)\n#    define attribute_deprecated __attribute__((deprecated))\n#elif defined(_MSC_VER)\n#    define attribute_deprecated __declspec(deprecated)\n#else\n#    define attribute_deprecated\n#endif\n\n/**\n * Disable warnings about deprecated features\n * This is useful for sections of code kept for backward compatibility and\n * scheduled for removal.\n */\n#ifndef AV_NOWARN_DEPRECATED\n#if AV_GCC_VERSION_AT_LEAST(4,6) || defined(__clang__)\n#    define AV_NOWARN_DEPRECATED(code) \\\n        _Pragma(\"GCC diagnostic push\") \\\n        _Pragma(\"GCC diagnostic ignored \\\"-Wdeprecated-declarations\\\"\") \\\n        code \\\n        _Pragma(\"GCC diagnostic pop\")\n#elif defined(_MSC_VER)\n#    define AV_NOWARN_DEPRECATED(code) \\\n        __pragma(warning(push)) \\\n        __pragma(warning(disable : 4996)) \\\n        code; \\\n        __pragma(warning(pop))\n#else\n#    define AV_NOWARN_DEPRECATED(code) code\n#endif\n#endif\n\n#if defined(__GNUC__) || defined(__clang__)\n#    define av_unused __attribute__((unused))\n#else\n#    define av_unused\n#endif\n\n/**\n * Mark a variable as used and prevent the compiler from optimizing it\n * away.  This is useful for variables accessed only from inline\n * assembler without the compiler being aware.\n */\n#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__)\n#    define av_used __attribute__((used))\n#else\n#    define av_used\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__)\n#   define av_alias __attribute__((may_alias))\n#else\n#   define av_alias\n#endif\n\n#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER)\n#    define av_uninit(x) x=x\n#else\n#    define av_uninit(x) x\n#endif\n\n#if defined(__GNUC__) || defined(__clang__)\n#    define av_builtin_constant_p __builtin_constant_p\n#    define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos)))\n#else\n#    define av_builtin_constant_p(x) 0\n#    define av_printf_format(fmtpos, attrpos)\n#endif\n\n#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__)\n#    define av_noreturn __attribute__((noreturn))\n#else\n#    define av_noreturn\n#endif\n\n#endif /* AVUTIL_ATTRIBUTES_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/audio_fifo.h",
    "content": "/*\n * Audio FIFO\n * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * Audio FIFO Buffer\n */\n\n#ifndef AVUTIL_AUDIO_FIFO_H\n#define AVUTIL_AUDIO_FIFO_H\n\n#include \"attributes.h\"\n#include \"samplefmt.h\"\n\n/**\n * @addtogroup lavu_audio\n * @{\n *\n * @defgroup lavu_audiofifo Audio FIFO Buffer\n * @{\n */\n\n/**\n * Context for an Audio FIFO Buffer.\n *\n * - Operates at the sample level rather than the byte level.\n * - Supports multiple channels with either planar or packed sample format.\n * - Automatic reallocation when writing to a full buffer.\n */\ntypedef struct AVAudioFifo AVAudioFifo;\n\n/**\n * Free an AVAudioFifo.\n *\n * @param af  AVAudioFifo to free\n */\nvoid av_audio_fifo_free(AVAudioFifo *af);\n\n/**\n * Allocate an AVAudioFifo.\n *\n * @param sample_fmt  sample format\n * @param channels    number of channels\n * @param nb_samples  initial allocation size, in samples\n * @return            newly allocated AVAudioFifo, or NULL on error\n */\nAVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,\n                                 int nb_samples);\n\n/**\n * Reallocate an AVAudioFifo.\n *\n * @param af          AVAudioFifo to reallocate\n * @param nb_samples  new allocation size, in samples\n * @return            0 if OK, or negative AVERROR code on failure\n */\nav_warn_unused_result\nint av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples);\n\n/**\n * Write data to an AVAudioFifo.\n *\n * The AVAudioFifo will be reallocated automatically if the available space\n * is less than nb_samples.\n *\n * @see enum AVSampleFormat\n * The documentation for AVSampleFormat describes the data layout.\n *\n * @param af          AVAudioFifo to write to\n * @param data        audio data plane pointers\n * @param nb_samples  number of samples to write\n * @return            number of samples actually written, or negative AVERROR\n *                    code on failure. If successful, the number of samples\n *                    actually written will always be nb_samples.\n */\nint av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples);\n\n/**\n * Peek data from an AVAudioFifo.\n *\n * @see enum AVSampleFormat\n * The documentation for AVSampleFormat describes the data layout.\n *\n * @param af          AVAudioFifo to read from\n * @param data        audio data plane pointers\n * @param nb_samples  number of samples to peek\n * @return            number of samples actually peek, or negative AVERROR code\n *                    on failure. The number of samples actually peek will not\n *                    be greater than nb_samples, and will only be less than\n *                    nb_samples if av_audio_fifo_size is less than nb_samples.\n */\nint av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples);\n\n/**\n * Peek data from an AVAudioFifo.\n *\n * @see enum AVSampleFormat\n * The documentation for AVSampleFormat describes the data layout.\n *\n * @param af          AVAudioFifo to read from\n * @param data        audio data plane pointers\n * @param nb_samples  number of samples to peek\n * @param offset      offset from current read position\n * @return            number of samples actually peek, or negative AVERROR code\n *                    on failure. The number of samples actually peek will not\n *                    be greater than nb_samples, and will only be less than\n *                    nb_samples if av_audio_fifo_size is less than nb_samples.\n */\nint av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset);\n\n/**\n * Read data from an AVAudioFifo.\n *\n * @see enum AVSampleFormat\n * The documentation for AVSampleFormat describes the data layout.\n *\n * @param af          AVAudioFifo to read from\n * @param data        audio data plane pointers\n * @param nb_samples  number of samples to read\n * @return            number of samples actually read, or negative AVERROR code\n *                    on failure. The number of samples actually read will not\n *                    be greater than nb_samples, and will only be less than\n *                    nb_samples if av_audio_fifo_size is less than nb_samples.\n */\nint av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples);\n\n/**\n * Drain data from an AVAudioFifo.\n *\n * Removes the data without reading it.\n *\n * @param af          AVAudioFifo to drain\n * @param nb_samples  number of samples to drain\n * @return            0 if OK, or negative AVERROR code on failure\n */\nint av_audio_fifo_drain(AVAudioFifo *af, int nb_samples);\n\n/**\n * Reset the AVAudioFifo buffer.\n *\n * This empties all data in the buffer.\n *\n * @param af  AVAudioFifo to reset\n */\nvoid av_audio_fifo_reset(AVAudioFifo *af);\n\n/**\n * Get the current number of samples in the AVAudioFifo available for reading.\n *\n * @param af  the AVAudioFifo to query\n * @return    number of samples available for reading\n */\nint av_audio_fifo_size(AVAudioFifo *af);\n\n/**\n * Get the current number of samples in the AVAudioFifo available for writing.\n *\n * @param af  the AVAudioFifo to query\n * @return    number of samples available for writing\n */\nint av_audio_fifo_space(AVAudioFifo *af);\n\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_AUDIO_FIFO_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/avassert.h",
    "content": "/*\n * copyright (c) 2010 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * simple assert() macros that are a bit more flexible than ISO C assert().\n * @author Michael Niedermayer <michaelni@gmx.at>\n */\n\n#ifndef AVUTIL_AVASSERT_H\n#define AVUTIL_AVASSERT_H\n\n#include <stdlib.h>\n#include \"log.h\"\n#include \"macros.h\"\n\n/**\n * assert() equivalent, that is always enabled.\n */\n#define av_assert0(cond) do {                                           \\\n    if (!(cond)) {                                                      \\\n        av_log(NULL, AV_LOG_PANIC, \"Assertion %s failed at %s:%d\\n\",    \\\n               AV_STRINGIFY(cond), __FILE__, __LINE__);                 \\\n        abort();                                                        \\\n    }                                                                   \\\n} while (0)\n\n\n/**\n * assert() equivalent, that does not lie in speed critical code.\n * These asserts() thus can be enabled without fearing speed loss.\n */\n#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0\n#define av_assert1(cond) av_assert0(cond)\n#else\n#define av_assert1(cond) ((void)0)\n#endif\n\n\n/**\n * assert() equivalent, that does lie in speed critical code.\n */\n#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1\n#define av_assert2(cond) av_assert0(cond)\n#define av_assert2_fpu() av_assert0_fpu()\n#else\n#define av_assert2(cond) ((void)0)\n#define av_assert2_fpu() ((void)0)\n#endif\n\n/**\n * Assert that floating point operations can be executed.\n *\n * This will av_assert0() that the cpu is not in MMX state on X86\n */\nvoid av_assert0_fpu(void);\n\n#endif /* AVUTIL_AVASSERT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/avconfig.h",
    "content": "/* Generated by ffmpeg configure */\n#ifndef AVUTIL_AVCONFIG_H\n#define AVUTIL_AVCONFIG_H\n#define AV_HAVE_BIGENDIAN 0\n#define AV_HAVE_FAST_UNALIGNED 1\n#endif /* AVUTIL_AVCONFIG_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/avstring.h",
    "content": "/*\n * Copyright (c) 2007 Mans Rullgard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_AVSTRING_H\n#define AVUTIL_AVSTRING_H\n\n#include <stddef.h>\n#include <stdint.h>\n#include \"attributes.h\"\n#include \"version.h\"\n\n/**\n * @addtogroup lavu_string\n * @{\n */\n\n/**\n * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to\n * the address of the first character in str after the prefix.\n *\n * @param str input string\n * @param pfx prefix to test\n * @param ptr updated if the prefix is matched inside str\n * @return non-zero if the prefix matches, zero otherwise\n */\nint av_strstart(const char *str, const char *pfx, const char **ptr);\n\n/**\n * Return non-zero if pfx is a prefix of str independent of case. If\n * it is, *ptr is set to the address of the first character in str\n * after the prefix.\n *\n * @param str input string\n * @param pfx prefix to test\n * @param ptr updated if the prefix is matched inside str\n * @return non-zero if the prefix matches, zero otherwise\n */\nint av_stristart(const char *str, const char *pfx, const char **ptr);\n\n/**\n * Locate the first case-independent occurrence in the string haystack\n * of the string needle.  A zero-length string needle is considered to\n * match at the start of haystack.\n *\n * This function is a case-insensitive version of the standard strstr().\n *\n * @param haystack string to search in\n * @param needle   string to search for\n * @return         pointer to the located match within haystack\n *                 or a null pointer if no match\n */\nchar *av_stristr(const char *haystack, const char *needle);\n\n/**\n * Locate the first occurrence of the string needle in the string haystack\n * where not more than hay_length characters are searched. A zero-length\n * string needle is considered to match at the start of haystack.\n *\n * This function is a length-limited version of the standard strstr().\n *\n * @param haystack   string to search in\n * @param needle     string to search for\n * @param hay_length length of string to search in\n * @return           pointer to the located match within haystack\n *                   or a null pointer if no match\n */\nchar *av_strnstr(const char *haystack, const char *needle, size_t hay_length);\n\n/**\n * Copy the string src to dst, but no more than size - 1 bytes, and\n * null-terminate dst.\n *\n * This function is the same as BSD strlcpy().\n *\n * @param dst destination buffer\n * @param src source string\n * @param size size of destination buffer\n * @return the length of src\n *\n * @warning since the return value is the length of src, src absolutely\n * _must_ be a properly 0-terminated string, otherwise this will read beyond\n * the end of the buffer and possibly crash.\n */\nsize_t av_strlcpy(char *dst, const char *src, size_t size);\n\n/**\n * Append the string src to the string dst, but to a total length of\n * no more than size - 1 bytes, and null-terminate dst.\n *\n * This function is similar to BSD strlcat(), but differs when\n * size <= strlen(dst).\n *\n * @param dst destination buffer\n * @param src source string\n * @param size size of destination buffer\n * @return the total length of src and dst\n *\n * @warning since the return value use the length of src and dst, these\n * absolutely _must_ be a properly 0-terminated strings, otherwise this\n * will read beyond the end of the buffer and possibly crash.\n */\nsize_t av_strlcat(char *dst, const char *src, size_t size);\n\n/**\n * Append output to a string, according to a format. Never write out of\n * the destination buffer, and always put a terminating 0 within\n * the buffer.\n * @param dst destination buffer (string to which the output is\n *  appended)\n * @param size total size of the destination buffer\n * @param fmt printf-compatible format string, specifying how the\n *  following parameters are used\n * @return the length of the string that would have been generated\n *  if enough space had been available\n */\nsize_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4);\n\n/**\n * Get the count of continuous non zero chars starting from the beginning.\n *\n * @param len maximum number of characters to check in the string, that\n *            is the maximum value which is returned by the function\n */\nstatic inline size_t av_strnlen(const char *s, size_t len)\n{\n    size_t i;\n    for (i = 0; i < len && s[i]; i++)\n        ;\n    return i;\n}\n\n/**\n * Print arguments following specified format into a large enough auto\n * allocated buffer. It is similar to GNU asprintf().\n * @param fmt printf-compatible format string, specifying how the\n *            following parameters are used.\n * @return the allocated string\n * @note You have to free the string yourself with av_free().\n */\nchar *av_asprintf(const char *fmt, ...) av_printf_format(1, 2);\n\n#if FF_API_D2STR\n/**\n * Convert a number to an av_malloced string.\n * @deprecated  use av_asprintf() with \"%f\" or a more specific format\n */\nattribute_deprecated\nchar *av_d2str(double d);\n#endif\n\n/**\n * Unescape the given string until a non escaped terminating char,\n * and return the token corresponding to the unescaped string.\n *\n * The normal \\ and ' escaping is supported. Leading and trailing\n * whitespaces are removed, unless they are escaped with '\\' or are\n * enclosed between ''.\n *\n * @param buf the buffer to parse, buf will be updated to point to the\n * terminating char\n * @param term a 0-terminated list of terminating chars\n * @return the malloced unescaped string, which must be av_freed by\n * the user, NULL in case of allocation failure\n */\nchar *av_get_token(const char **buf, const char *term);\n\n/**\n * Split the string into several tokens which can be accessed by\n * successive calls to av_strtok().\n *\n * A token is defined as a sequence of characters not belonging to the\n * set specified in delim.\n *\n * On the first call to av_strtok(), s should point to the string to\n * parse, and the value of saveptr is ignored. In subsequent calls, s\n * should be NULL, and saveptr should be unchanged since the previous\n * call.\n *\n * This function is similar to strtok_r() defined in POSIX.1.\n *\n * @param s the string to parse, may be NULL\n * @param delim 0-terminated list of token delimiters, must be non-NULL\n * @param saveptr user-provided pointer which points to stored\n * information necessary for av_strtok() to continue scanning the same\n * string. saveptr is updated to point to the next character after the\n * first delimiter found, or to NULL if the string was terminated\n * @return the found token, or NULL when no token is found\n */\nchar *av_strtok(char *s, const char *delim, char **saveptr);\n\n/**\n * Locale-independent conversion of ASCII isdigit.\n */\nstatic inline av_const int av_isdigit(int c)\n{\n    return c >= '0' && c <= '9';\n}\n\n/**\n * Locale-independent conversion of ASCII isgraph.\n */\nstatic inline av_const int av_isgraph(int c)\n{\n    return c > 32 && c < 127;\n}\n\n/**\n * Locale-independent conversion of ASCII isspace.\n */\nstatic inline av_const int av_isspace(int c)\n{\n    return c == ' ' || c == '\\f' || c == '\\n' || c == '\\r' || c == '\\t' ||\n           c == '\\v';\n}\n\n/**\n * Locale-independent conversion of ASCII characters to uppercase.\n */\nstatic inline av_const int av_toupper(int c)\n{\n    if (c >= 'a' && c <= 'z')\n        c ^= 0x20;\n    return c;\n}\n\n/**\n * Locale-independent conversion of ASCII characters to lowercase.\n */\nstatic inline av_const int av_tolower(int c)\n{\n    if (c >= 'A' && c <= 'Z')\n        c ^= 0x20;\n    return c;\n}\n\n/**\n * Locale-independent conversion of ASCII isxdigit.\n */\nstatic inline av_const int av_isxdigit(int c)\n{\n    c = av_tolower(c);\n    return av_isdigit(c) || (c >= 'a' && c <= 'f');\n}\n\n/**\n * Locale-independent case-insensitive compare.\n * @note This means only ASCII-range characters are case-insensitive\n */\nint av_strcasecmp(const char *a, const char *b);\n\n/**\n * Locale-independent case-insensitive compare.\n * @note This means only ASCII-range characters are case-insensitive\n */\nint av_strncasecmp(const char *a, const char *b, size_t n);\n\n/**\n * Locale-independent strings replace.\n * @note This means only ASCII-range characters are replace\n */\nchar *av_strireplace(const char *str, const char *from, const char *to);\n\n/**\n * Thread safe basename.\n * @param path the string to parse, on DOS both \\ and / are considered separators.\n * @return pointer to the basename substring.\n * If path does not contain a slash, the function returns a copy of path.\n * If path is a NULL pointer or points to an empty string, a pointer\n * to a string \".\" is returned.\n */\nconst char *av_basename(const char *path);\n\n/**\n * Thread safe dirname.\n * @param path the string to parse, on DOS both \\ and / are considered separators.\n * @return A pointer to a string that's the parent directory of path.\n * If path is a NULL pointer or points to an empty string, a pointer\n * to a string \".\" is returned.\n * @note the function may modify the contents of the path, so copies should be passed.\n */\nconst char *av_dirname(char *path);\n\n/**\n * Match instances of a name in a comma-separated list of names.\n * List entries are checked from the start to the end of the names list,\n * the first match ends further processing. If an entry prefixed with '-'\n * matches, then 0 is returned. The \"ALL\" list entry is considered to\n * match all names.\n *\n * @param name  Name to look for.\n * @param names List of names.\n * @return 1 on match, 0 otherwise.\n */\nint av_match_name(const char *name, const char *names);\n\n/**\n * Append path component to the existing path.\n * Path separator '/' is placed between when needed.\n * Resulting string have to be freed with av_free().\n * @param path      base path\n * @param component component to be appended\n * @return new path or NULL on error.\n */\nchar *av_append_path_component(const char *path, const char *component);\n\nenum AVEscapeMode {\n    AV_ESCAPE_MODE_AUTO,      ///< Use auto-selected escaping mode.\n    AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping.\n    AV_ESCAPE_MODE_QUOTE,     ///< Use single-quote escaping.\n    AV_ESCAPE_MODE_XML,       ///< Use XML non-markup character data escaping.\n};\n\n/**\n * Consider spaces special and escape them even in the middle of the\n * string.\n *\n * This is equivalent to adding the whitespace characters to the special\n * characters lists, except it is guaranteed to use the exact same list\n * of whitespace characters as the rest of libavutil.\n */\n#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0)\n\n/**\n * Escape only specified special characters.\n * Without this flag, escape also any characters that may be considered\n * special by av_get_token(), such as the single quote.\n */\n#define AV_ESCAPE_FLAG_STRICT (1 << 1)\n\n/**\n * Within AV_ESCAPE_MODE_XML, additionally escape single quotes for single\n * quoted attributes.\n */\n#define AV_ESCAPE_FLAG_XML_SINGLE_QUOTES (1 << 2)\n\n/**\n * Within AV_ESCAPE_MODE_XML, additionally escape double quotes for double\n * quoted attributes.\n */\n#define AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES (1 << 3)\n\n\n/**\n * Escape string in src, and put the escaped string in an allocated\n * string in *dst, which must be freed with av_free().\n *\n * @param dst           pointer where an allocated string is put\n * @param src           string to escape, must be non-NULL\n * @param special_chars string containing the special characters which\n *                      need to be escaped, can be NULL\n * @param mode          escape mode to employ, see AV_ESCAPE_MODE_* macros.\n *                      Any unknown value for mode will be considered equivalent to\n *                      AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without\n *                      notice.\n * @param flags         flags which control how to escape, see AV_ESCAPE_FLAG_ macros\n * @return the length of the allocated string, or a negative error code in case of error\n * @see av_bprint_escape()\n */\nav_warn_unused_result\nint av_escape(char **dst, const char *src, const char *special_chars,\n              enum AVEscapeMode mode, int flags);\n\n#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES          1 ///< accept codepoints over 0x10FFFF\n#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS             2 ///< accept non-characters - 0xFFFE and 0xFFFF\n#define AV_UTF8_FLAG_ACCEPT_SURROGATES                 4 ///< accept UTF-16 surrogates codes\n#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML\n\n#define AV_UTF8_FLAG_ACCEPT_ALL \\\n    AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES\n\n/**\n * Read and decode a single UTF-8 code point (character) from the\n * buffer in *buf, and update *buf to point to the next byte to\n * decode.\n *\n * In case of an invalid byte sequence, the pointer will be updated to\n * the next byte after the invalid sequence and the function will\n * return an error code.\n *\n * Depending on the specified flags, the function will also fail in\n * case the decoded code point does not belong to a valid range.\n *\n * @note For speed-relevant code a carefully implemented use of\n * GET_UTF8() may be preferred.\n *\n * @param codep   pointer used to return the parsed code in case of success.\n *                The value in *codep is set even in case the range check fails.\n * @param bufp    pointer to the address the first byte of the sequence\n *                to decode, updated by the function to point to the\n *                byte next after the decoded sequence\n * @param buf_end pointer to the end of the buffer, points to the next\n *                byte past the last in the buffer. This is used to\n *                avoid buffer overreads (in case of an unfinished\n *                UTF-8 sequence towards the end of the buffer).\n * @param flags   a collection of AV_UTF8_FLAG_* flags\n * @return >= 0 in case a sequence was successfully read, a negative\n * value in case of invalid sequence\n */\nav_warn_unused_result\nint av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end,\n                   unsigned int flags);\n\n/**\n * Check if a name is in a list.\n * @returns 0 if not found, or the 1 based index where it has been found in the\n *            list.\n */\nint av_match_list(const char *name, const char *list, char separator);\n\n/**\n * See libc sscanf manual for more information.\n * Locale-independent sscanf implementation.\n */\nint av_sscanf(const char *string, const char *format, ...);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_AVSTRING_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/avutil.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_AVUTIL_H\n#define AVUTIL_AVUTIL_H\n\n/**\n * @file\n * @ingroup lavu\n * Convenience header that includes @ref lavu \"libavutil\"'s core.\n */\n\n/**\n * @mainpage\n *\n * @section ffmpeg_intro Introduction\n *\n * This document describes the usage of the different libraries\n * provided by FFmpeg.\n *\n * @li @ref libavc \"libavcodec\" encoding/decoding library\n * @li @ref lavfi \"libavfilter\" graph-based frame editing library\n * @li @ref libavf \"libavformat\" I/O and muxing/demuxing library\n * @li @ref lavd \"libavdevice\" special devices muxing/demuxing library\n * @li @ref lavu \"libavutil\" common utility library\n * @li @ref lswr \"libswresample\" audio resampling, format conversion and mixing\n * @li @ref lpp  \"libpostproc\" post processing library\n * @li @ref libsws \"libswscale\" color conversion and scaling library\n *\n * @section ffmpeg_versioning Versioning and compatibility\n *\n * Each of the FFmpeg libraries contains a version.h header, which defines a\n * major, minor and micro version number with the\n * <em>LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO}</em> macros. The major version\n * number is incremented with backward incompatible changes - e.g. removing\n * parts of the public API, reordering public struct members, etc. The minor\n * version number is incremented for backward compatible API changes or major\n * new features - e.g. adding a new public function or a new decoder. The micro\n * version number is incremented for smaller changes that a calling program\n * might still want to check for - e.g. changing behavior in a previously\n * unspecified situation.\n *\n * FFmpeg guarantees backward API and ABI compatibility for each library as long\n * as its major version number is unchanged. This means that no public symbols\n * will be removed or renamed. Types and names of the public struct members and\n * values of public macros and enums will remain the same (unless they were\n * explicitly declared as not part of the public API). Documented behavior will\n * not change.\n *\n * In other words, any correct program that works with a given FFmpeg snapshot\n * should work just as well without any changes with any later snapshot with the\n * same major versions. This applies to both rebuilding the program against new\n * FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program\n * links against.\n *\n * However, new public symbols may be added and new members may be appended to\n * public structs whose size is not part of public ABI (most public structs in\n * FFmpeg). New macros and enum values may be added. Behavior in undocumented\n * situations may change slightly (and be documented). All those are accompanied\n * by an entry in doc/APIchanges and incrementing either the minor or micro\n * version number.\n */\n\n/**\n * @defgroup lavu libavutil\n * Common code shared across all FFmpeg libraries.\n *\n * @note\n * libavutil is designed to be modular. In most cases, in order to use the\n * functions provided by one component of libavutil you must explicitly include\n * the specific header containing that feature. If you are only using\n * media-related components, you could simply include libavutil/avutil.h, which\n * brings in most of the \"core\" components.\n *\n * @{\n *\n * @defgroup lavu_crypto Crypto and Hashing\n *\n * @{\n * @}\n *\n * @defgroup lavu_math Mathematics\n * @{\n *\n * @}\n *\n * @defgroup lavu_string String Manipulation\n *\n * @{\n *\n * @}\n *\n * @defgroup lavu_mem Memory Management\n *\n * @{\n *\n * @}\n *\n * @defgroup lavu_data Data Structures\n * @{\n *\n * @}\n *\n * @defgroup lavu_video Video related\n *\n * @{\n *\n * @}\n *\n * @defgroup lavu_audio Audio related\n *\n * @{\n *\n * @}\n *\n * @defgroup lavu_error Error Codes\n *\n * @{\n *\n * @}\n *\n * @defgroup lavu_log Logging Facility\n *\n * @{\n *\n * @}\n *\n * @defgroup lavu_misc Other\n *\n * @{\n *\n * @defgroup preproc_misc Preprocessor String Macros\n *\n * @{\n *\n * @}\n *\n * @defgroup version_utils Library Version Macros\n *\n * @{\n *\n * @}\n */\n\n\n/**\n * @addtogroup lavu_ver\n * @{\n */\n\n/**\n * Return the LIBAVUTIL_VERSION_INT constant.\n */\nunsigned avutil_version(void);\n\n/**\n * Return an informative version string. This usually is the actual release\n * version number or a git commit description. This string has no fixed format\n * and can change any time. It should never be parsed by code.\n */\nconst char *av_version_info(void);\n\n/**\n * Return the libavutil build-time configuration.\n */\nconst char *avutil_configuration(void);\n\n/**\n * Return the libavutil license.\n */\nconst char *avutil_license(void);\n\n/**\n * @}\n */\n\n/**\n * @addtogroup lavu_media Media Type\n * @brief Media Type\n */\n\nenum AVMediaType {\n    AVMEDIA_TYPE_UNKNOWN = -1,  ///< Usually treated as AVMEDIA_TYPE_DATA\n    AVMEDIA_TYPE_VIDEO,\n    AVMEDIA_TYPE_AUDIO,\n    AVMEDIA_TYPE_DATA,          ///< Opaque data information usually continuous\n    AVMEDIA_TYPE_SUBTITLE,\n    AVMEDIA_TYPE_ATTACHMENT,    ///< Opaque data information usually sparse\n    AVMEDIA_TYPE_NB\n};\n\n/**\n * Return a string describing the media_type enum, NULL if media_type\n * is unknown.\n */\nconst char *av_get_media_type_string(enum AVMediaType media_type);\n\n/**\n * @defgroup lavu_const Constants\n * @{\n *\n * @defgroup lavu_enc Encoding specific\n *\n * @note those definition should move to avcodec\n * @{\n */\n\n#define FF_LAMBDA_SHIFT 7\n#define FF_LAMBDA_SCALE (1<<FF_LAMBDA_SHIFT)\n#define FF_QP2LAMBDA 118 ///< factor to convert from H.263 QP to lambda\n#define FF_LAMBDA_MAX (256*128-1)\n\n#define FF_QUALITY_SCALE FF_LAMBDA_SCALE //FIXME maybe remove\n\n/**\n * @}\n * @defgroup lavu_time Timestamp specific\n *\n * FFmpeg internal timebase and timestamp definitions\n *\n * @{\n */\n\n/**\n * @brief Undefined timestamp value\n *\n * Usually reported by demuxer that work on containers that do not provide\n * either pts or dts.\n */\n\n#define AV_NOPTS_VALUE          ((int64_t)UINT64_C(0x8000000000000000))\n\n/**\n * Internal time base represented as integer\n */\n\n#define AV_TIME_BASE            1000000\n\n/**\n * Internal time base represented as fractional value\n */\n\n#define AV_TIME_BASE_Q          (AVRational){1, AV_TIME_BASE}\n\n/**\n * @}\n * @}\n * @defgroup lavu_picture Image related\n *\n * AVPicture types, pixel formats and basic image planes manipulation.\n *\n * @{\n */\n\nenum AVPictureType {\n    AV_PICTURE_TYPE_NONE = 0, ///< Undefined\n    AV_PICTURE_TYPE_I,     ///< Intra\n    AV_PICTURE_TYPE_P,     ///< Predicted\n    AV_PICTURE_TYPE_B,     ///< Bi-dir predicted\n    AV_PICTURE_TYPE_S,     ///< S(GMC)-VOP MPEG-4\n    AV_PICTURE_TYPE_SI,    ///< Switching Intra\n    AV_PICTURE_TYPE_SP,    ///< Switching Predicted\n    AV_PICTURE_TYPE_BI,    ///< BI type\n};\n\n/**\n * Return a single letter to describe the given picture type\n * pict_type.\n *\n * @param[in] pict_type the picture type @return a single character\n * representing the picture type, '?' if pict_type is unknown\n */\nchar av_get_picture_type_char(enum AVPictureType pict_type);\n\n/**\n * @}\n */\n\n#include \"common.h\"\n#include \"error.h\"\n#include \"rational.h\"\n#include \"version.h\"\n#include \"macros.h\"\n#include \"mathematics.h\"\n#include \"log.h\"\n#include \"pixfmt.h\"\n\n/**\n * Return x default pointer in case p is NULL.\n */\nstatic inline void *av_x_if_null(const void *p, const void *x)\n{\n    return (void *)(intptr_t)(p ? p : x);\n}\n\n/**\n * Compute the length of an integer list.\n *\n * @param elsize  size in bytes of each list element (only 1, 2, 4 or 8)\n * @param term    list terminator (usually 0 or -1)\n * @param list    pointer to the list\n * @return  length of the list, in elements, not counting the terminator\n */\nunsigned av_int_list_length_for_size(unsigned elsize,\n                                     const void *list, uint64_t term) av_pure;\n\n/**\n * Compute the length of an integer list.\n *\n * @param term  list terminator (usually 0 or -1)\n * @param list  pointer to the list\n * @return  length of the list, in elements, not counting the terminator\n */\n#define av_int_list_length(list, term) \\\n    av_int_list_length_for_size(sizeof(*(list)), list, term)\n\n#if FF_API_AV_FOPEN_UTF8\n/**\n * Open a file using a UTF-8 filename.\n * The API of this function matches POSIX fopen(), errors are returned through\n * errno.\n * @deprecated Avoid using it, as on Windows, the FILE* allocated by this\n *             function may be allocated with a different CRT than the caller\n *             who uses the FILE*. No replacement provided in public API.\n */\nattribute_deprecated\nFILE *av_fopen_utf8(const char *path, const char *mode);\n#endif\n\n/**\n * Return the fractional representation of the internal time base.\n */\nAVRational av_get_time_base_q(void);\n\n#define AV_FOURCC_MAX_STRING_SIZE 32\n\n#define av_fourcc2str(fourcc) av_fourcc_make_string((char[AV_FOURCC_MAX_STRING_SIZE]){0}, fourcc)\n\n/**\n * Fill the provided buffer with a string containing a FourCC (four-character\n * code) representation.\n *\n * @param buf    a buffer with size in bytes of at least AV_FOURCC_MAX_STRING_SIZE\n * @param fourcc the fourcc to represent\n * @return the buffer in input\n */\nchar *av_fourcc_make_string(char *buf, uint32_t fourcc);\n\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_AVUTIL_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/base64.h",
    "content": "/*\n * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_BASE64_H\n#define AVUTIL_BASE64_H\n\n#include <stdint.h>\n\n/**\n * @defgroup lavu_base64 Base64\n * @ingroup lavu_crypto\n * @{\n */\n\n/**\n * Decode a base64-encoded string.\n *\n * @param out      buffer for decoded data\n * @param in       null-terminated input string\n * @param out_size size in bytes of the out buffer, must be at\n *                 least 3/4 of the length of in, that is AV_BASE64_DECODE_SIZE(strlen(in))\n * @return         number of bytes written, or a negative value in case of\n *                 invalid input\n */\nint av_base64_decode(uint8_t *out, const char *in, int out_size);\n\n/**\n * Calculate the output size in bytes needed to decode a base64 string\n * with length x to a data buffer.\n */\n#define AV_BASE64_DECODE_SIZE(x) ((x) * 3LL / 4)\n\n/**\n * Encode data to base64 and null-terminate.\n *\n * @param out      buffer for encoded data\n * @param out_size size in bytes of the out buffer (including the\n *                 null terminator), must be at least AV_BASE64_SIZE(in_size)\n * @param in       input buffer containing the data to encode\n * @param in_size  size in bytes of the in buffer\n * @return         out or NULL in case of error\n */\nchar *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size);\n\n/**\n * Calculate the output size needed to base64-encode x bytes to a\n * null-terminated string.\n */\n#define AV_BASE64_SIZE(x)  (((x)+2) / 3 * 4 + 1)\n\n /**\n  * @}\n  */\n\n#endif /* AVUTIL_BASE64_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/blowfish.h",
    "content": "/*\n * Blowfish algorithm\n * Copyright (c) 2012 Samuel Pitoiset\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_BLOWFISH_H\n#define AVUTIL_BLOWFISH_H\n\n#include <stdint.h>\n\n/**\n * @defgroup lavu_blowfish Blowfish\n * @ingroup lavu_crypto\n * @{\n */\n\n#define AV_BF_ROUNDS 16\n\ntypedef struct AVBlowfish {\n    uint32_t p[AV_BF_ROUNDS + 2];\n    uint32_t s[4][256];\n} AVBlowfish;\n\n/**\n * Allocate an AVBlowfish context.\n */\nAVBlowfish *av_blowfish_alloc(void);\n\n/**\n * Initialize an AVBlowfish context.\n *\n * @param ctx an AVBlowfish context\n * @param key a key\n * @param key_len length of the key\n */\nvoid av_blowfish_init(struct AVBlowfish *ctx, const uint8_t *key, int key_len);\n\n/**\n * Encrypt or decrypt a buffer using a previously initialized context.\n *\n * @param ctx an AVBlowfish context\n * @param xl left four bytes halves of input to be encrypted\n * @param xr right four bytes halves of input to be encrypted\n * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_blowfish_crypt_ecb(struct AVBlowfish *ctx, uint32_t *xl, uint32_t *xr,\n                           int decrypt);\n\n/**\n * Encrypt or decrypt a buffer using a previously initialized context.\n *\n * @param ctx an AVBlowfish context\n * @param dst destination array, can be equal to src\n * @param src source array, can be equal to dst\n * @param count number of 8 byte blocks\n * @param iv initialization vector for CBC mode, if NULL ECB will be used\n * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_blowfish_crypt(struct AVBlowfish *ctx, uint8_t *dst, const uint8_t *src,\n                       int count, uint8_t *iv, int decrypt);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_BLOWFISH_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/bprint.h",
    "content": "/*\n * Copyright (c) 2012 Nicolas George\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_BPRINT_H\n#define AVUTIL_BPRINT_H\n\n#include <stdarg.h>\n\n#include \"attributes.h\"\n#include \"avstring.h\"\n\n/**\n * Define a structure with extra padding to a fixed size\n * This helps ensuring binary compatibility with future versions.\n */\n\n#define FF_PAD_STRUCTURE(name, size, ...) \\\nstruct ff_pad_helper_##name { __VA_ARGS__ }; \\\ntypedef struct name { \\\n    __VA_ARGS__ \\\n    char reserved_padding[size - sizeof(struct ff_pad_helper_##name)]; \\\n} name;\n\n/**\n * Buffer to print data progressively\n *\n * The string buffer grows as necessary and is always 0-terminated.\n * The content of the string is never accessed, and thus is\n * encoding-agnostic and can even hold binary data.\n *\n * Small buffers are kept in the structure itself, and thus require no\n * memory allocation at all (unless the contents of the buffer is needed\n * after the structure goes out of scope). This is almost as lightweight as\n * declaring a local \"char buf[512]\".\n *\n * The length of the string can go beyond the allocated size: the buffer is\n * then truncated, but the functions still keep account of the actual total\n * length.\n *\n * In other words, buf->len can be greater than buf->size and records the\n * total length of what would have been to the buffer if there had been\n * enough memory.\n *\n * Append operations do not need to be tested for failure: if a memory\n * allocation fails, data stop being appended to the buffer, but the length\n * is still updated. This situation can be tested with\n * av_bprint_is_complete().\n *\n * The size_max field determines several possible behaviours:\n *\n * size_max = -1 (= UINT_MAX) or any large value will let the buffer be\n * reallocated as necessary, with an amortized linear cost.\n *\n * size_max = 0 prevents writing anything to the buffer: only the total\n * length is computed. The write operations can then possibly be repeated in\n * a buffer with exactly the necessary size\n * (using size_init = size_max = len + 1).\n *\n * size_max = 1 is automatically replaced by the exact size available in the\n * structure itself, thus ensuring no dynamic memory allocation. The\n * internal buffer is large enough to hold a reasonable paragraph of text,\n * such as the current paragraph.\n */\n\nFF_PAD_STRUCTURE(AVBPrint, 1024,\n    char *str;         /**< string so far */\n    unsigned len;      /**< length so far */\n    unsigned size;     /**< allocated memory */\n    unsigned size_max; /**< maximum allocated memory */\n    char reserved_internal_buffer[1];\n)\n\n/**\n * Convenience macros for special values for av_bprint_init() size_max\n * parameter.\n */\n#define AV_BPRINT_SIZE_UNLIMITED  ((unsigned)-1)\n#define AV_BPRINT_SIZE_AUTOMATIC  1\n#define AV_BPRINT_SIZE_COUNT_ONLY 0\n\n/**\n * Init a print buffer.\n *\n * @param buf        buffer to init\n * @param size_init  initial size (including the final 0)\n * @param size_max   maximum size;\n *                   0 means do not write anything, just count the length;\n *                   1 is replaced by the maximum value for automatic storage;\n *                   any large value means that the internal buffer will be\n *                   reallocated as needed up to that limit; -1 is converted to\n *                   UINT_MAX, the largest limit possible.\n *                   Check also AV_BPRINT_SIZE_* macros.\n */\nvoid av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max);\n\n/**\n * Init a print buffer using a pre-existing buffer.\n *\n * The buffer will not be reallocated.\n *\n * @param buf     buffer structure to init\n * @param buffer  byte buffer to use for the string data\n * @param size    size of buffer\n */\nvoid av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size);\n\n/**\n * Append a formatted string to a print buffer.\n */\nvoid av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3);\n\n/**\n * Append a formatted string to a print buffer.\n */\nvoid av_vbprintf(AVBPrint *buf, const char *fmt, va_list vl_arg);\n\n/**\n * Append char c n times to a print buffer.\n */\nvoid av_bprint_chars(AVBPrint *buf, char c, unsigned n);\n\n/**\n * Append data to a print buffer.\n *\n * param buf  bprint buffer to use\n * param data pointer to data\n * param size size of data\n */\nvoid av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size);\n\nstruct tm;\n/**\n * Append a formatted date and time to a print buffer.\n *\n * param buf  bprint buffer to use\n * param fmt  date and time format string, see strftime()\n * param tm   broken-down time structure to translate\n *\n * @note due to poor design of the standard strftime function, it may\n * produce poor results if the format string expands to a very long text and\n * the bprint buffer is near the limit stated by the size_max option.\n */\nvoid av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm);\n\n/**\n * Allocate bytes in the buffer for external use.\n *\n * @param[in]  buf          buffer structure\n * @param[in]  size         required size\n * @param[out] mem          pointer to the memory area\n * @param[out] actual_size  size of the memory area after allocation;\n *                          can be larger or smaller than size\n */\nvoid av_bprint_get_buffer(AVBPrint *buf, unsigned size,\n                          unsigned char **mem, unsigned *actual_size);\n\n/**\n * Reset the string to \"\" but keep internal allocated data.\n */\nvoid av_bprint_clear(AVBPrint *buf);\n\n/**\n * Test if the print buffer is complete (not truncated).\n *\n * It may have been truncated due to a memory allocation failure\n * or the size_max limit (compare size and size_max if necessary).\n */\nstatic inline int av_bprint_is_complete(const AVBPrint *buf)\n{\n    return buf->len < buf->size;\n}\n\n/**\n * Finalize a print buffer.\n *\n * The print buffer can no longer be used afterwards,\n * but the len and size fields are still valid.\n *\n * @arg[out] ret_str  if not NULL, used to return a permanent copy of the\n *                    buffer contents, or NULL if memory allocation fails;\n *                    if NULL, the buffer is discarded and freed\n * @return  0 for success or error code (probably AVERROR(ENOMEM))\n */\nint av_bprint_finalize(AVBPrint *buf, char **ret_str);\n\n/**\n * Escape the content in src and append it to dstbuf.\n *\n * @param dstbuf        already inited destination bprint buffer\n * @param src           string containing the text to escape\n * @param special_chars string containing the special characters which\n *                      need to be escaped, can be NULL\n * @param mode          escape mode to employ, see AV_ESCAPE_MODE_* macros.\n *                      Any unknown value for mode will be considered equivalent to\n *                      AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without\n *                      notice.\n * @param flags         flags which control how to escape, see AV_ESCAPE_FLAG_* macros\n */\nvoid av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars,\n                      enum AVEscapeMode mode, int flags);\n\n#endif /* AVUTIL_BPRINT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/bswap.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * byte swapping routines\n */\n\n#ifndef AVUTIL_BSWAP_H\n#define AVUTIL_BSWAP_H\n\n#include <stdint.h>\n#include \"libavutil/avconfig.h\"\n#include \"attributes.h\"\n\n#ifdef HAVE_AV_CONFIG_H\n\n#include \"config.h\"\n\n#if   ARCH_AARCH64\n#   include \"aarch64/bswap.h\"\n#elif ARCH_ARM\n#   include \"arm/bswap.h\"\n#elif ARCH_AVR32\n#   include \"avr32/bswap.h\"\n#elif ARCH_SH4\n#   include \"sh4/bswap.h\"\n#elif ARCH_X86\n#   include \"x86/bswap.h\"\n#endif\n\n#endif /* HAVE_AV_CONFIG_H */\n\n#define AV_BSWAP16C(x) (((x) << 8 & 0xff00)  | ((x) >> 8 & 0x00ff))\n#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))\n#define AV_BSWAP64C(x) (AV_BSWAP32C(x) << 32 | AV_BSWAP32C((x) >> 32))\n\n#define AV_BSWAPC(s, x) AV_BSWAP##s##C(x)\n\n#ifndef av_bswap16\nstatic av_always_inline av_const uint16_t av_bswap16(uint16_t x)\n{\n    x= (x>>8) | (x<<8);\n    return x;\n}\n#endif\n\n#ifndef av_bswap32\nstatic av_always_inline av_const uint32_t av_bswap32(uint32_t x)\n{\n    return AV_BSWAP32C(x);\n}\n#endif\n\n#ifndef av_bswap64\nstatic inline uint64_t av_const av_bswap64(uint64_t x)\n{\n    return (uint64_t)av_bswap32(x) << 32 | av_bswap32(x >> 32);\n}\n#endif\n\n// be2ne ... big-endian to native-endian\n// le2ne ... little-endian to native-endian\n\n#if AV_HAVE_BIGENDIAN\n#define av_be2ne16(x) (x)\n#define av_be2ne32(x) (x)\n#define av_be2ne64(x) (x)\n#define av_le2ne16(x) av_bswap16(x)\n#define av_le2ne32(x) av_bswap32(x)\n#define av_le2ne64(x) av_bswap64(x)\n#define AV_BE2NEC(s, x) (x)\n#define AV_LE2NEC(s, x) AV_BSWAPC(s, x)\n#else\n#define av_be2ne16(x) av_bswap16(x)\n#define av_be2ne32(x) av_bswap32(x)\n#define av_be2ne64(x) av_bswap64(x)\n#define av_le2ne16(x) (x)\n#define av_le2ne32(x) (x)\n#define av_le2ne64(x) (x)\n#define AV_BE2NEC(s, x) AV_BSWAPC(s, x)\n#define AV_LE2NEC(s, x) (x)\n#endif\n\n#define AV_BE2NE16C(x) AV_BE2NEC(16, x)\n#define AV_BE2NE32C(x) AV_BE2NEC(32, x)\n#define AV_BE2NE64C(x) AV_BE2NEC(64, x)\n#define AV_LE2NE16C(x) AV_LE2NEC(16, x)\n#define AV_LE2NE32C(x) AV_LE2NEC(32, x)\n#define AV_LE2NE64C(x) AV_LE2NEC(64, x)\n\n#endif /* AVUTIL_BSWAP_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/buffer.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_buffer\n * refcounted data buffer API\n */\n\n#ifndef AVUTIL_BUFFER_H\n#define AVUTIL_BUFFER_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * @defgroup lavu_buffer AVBuffer\n * @ingroup lavu_data\n *\n * @{\n * AVBuffer is an API for reference-counted data buffers.\n *\n * There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer\n * represents the data buffer itself; it is opaque and not meant to be accessed\n * by the caller directly, but only through AVBufferRef. However, the caller may\n * e.g. compare two AVBuffer pointers to check whether two different references\n * are describing the same data buffer. AVBufferRef represents a single\n * reference to an AVBuffer and it is the object that may be manipulated by the\n * caller directly.\n *\n * There are two functions provided for creating a new AVBuffer with a single\n * reference -- av_buffer_alloc() to just allocate a new buffer, and\n * av_buffer_create() to wrap an existing array in an AVBuffer. From an existing\n * reference, additional references may be created with av_buffer_ref().\n * Use av_buffer_unref() to free a reference (this will automatically free the\n * data once all the references are freed).\n *\n * The convention throughout this API and the rest of FFmpeg is such that the\n * buffer is considered writable if there exists only one reference to it (and\n * it has not been marked as read-only). The av_buffer_is_writable() function is\n * provided to check whether this is true and av_buffer_make_writable() will\n * automatically create a new writable buffer when necessary.\n * Of course nothing prevents the calling code from violating this convention,\n * however that is safe only when all the existing references are under its\n * control.\n *\n * @note Referencing and unreferencing the buffers is thread-safe and thus\n * may be done from multiple threads simultaneously without any need for\n * additional locking.\n *\n * @note Two different references to the same buffer can point to different\n * parts of the buffer (i.e. their AVBufferRef.data will not be equal).\n */\n\n/**\n * A reference counted buffer type. It is opaque and is meant to be used through\n * references (AVBufferRef).\n */\ntypedef struct AVBuffer AVBuffer;\n\n/**\n * A reference to a data buffer.\n *\n * The size of this struct is not a part of the public ABI and it is not meant\n * to be allocated directly.\n */\ntypedef struct AVBufferRef {\n    AVBuffer *buffer;\n\n    /**\n     * The data buffer. It is considered writable if and only if\n     * this is the only reference to the buffer, in which case\n     * av_buffer_is_writable() returns 1.\n     */\n    uint8_t *data;\n    /**\n     * Size of data in bytes.\n     */\n    size_t   size;\n} AVBufferRef;\n\n/**\n * Allocate an AVBuffer of the given size using av_malloc().\n *\n * @return an AVBufferRef of given size or NULL when out of memory\n */\nAVBufferRef *av_buffer_alloc(size_t size);\n\n/**\n * Same as av_buffer_alloc(), except the returned buffer will be initialized\n * to zero.\n */\nAVBufferRef *av_buffer_allocz(size_t size);\n\n/**\n * Always treat the buffer as read-only, even when it has only one\n * reference.\n */\n#define AV_BUFFER_FLAG_READONLY (1 << 0)\n\n/**\n * Create an AVBuffer from an existing array.\n *\n * If this function is successful, data is owned by the AVBuffer. The caller may\n * only access data through the returned AVBufferRef and references derived from\n * it.\n * If this function fails, data is left untouched.\n * @param data   data array\n * @param size   size of data in bytes\n * @param free   a callback for freeing this buffer's data\n * @param opaque parameter to be got for processing or passed to free\n * @param flags  a combination of AV_BUFFER_FLAG_*\n *\n * @return an AVBufferRef referring to data on success, NULL on failure.\n */\nAVBufferRef *av_buffer_create(uint8_t *data, size_t size,\n                              void (*free)(void *opaque, uint8_t *data),\n                              void *opaque, int flags);\n\n/**\n * Default free callback, which calls av_free() on the buffer data.\n * This function is meant to be passed to av_buffer_create(), not called\n * directly.\n */\nvoid av_buffer_default_free(void *opaque, uint8_t *data);\n\n/**\n * Create a new reference to an AVBuffer.\n *\n * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on\n * failure.\n */\nAVBufferRef *av_buffer_ref(const AVBufferRef *buf);\n\n/**\n * Free a given reference and automatically free the buffer if there are no more\n * references to it.\n *\n * @param buf the reference to be freed. The pointer is set to NULL on return.\n */\nvoid av_buffer_unref(AVBufferRef **buf);\n\n/**\n * @return 1 if the caller may write to the data referred to by buf (which is\n * true if and only if buf is the only reference to the underlying AVBuffer).\n * Return 0 otherwise.\n * A positive answer is valid until av_buffer_ref() is called on buf.\n */\nint av_buffer_is_writable(const AVBufferRef *buf);\n\n/**\n * @return the opaque parameter set by av_buffer_create.\n */\nvoid *av_buffer_get_opaque(const AVBufferRef *buf);\n\nint av_buffer_get_ref_count(const AVBufferRef *buf);\n\n/**\n * Create a writable reference from a given buffer reference, avoiding data copy\n * if possible.\n *\n * @param buf buffer reference to make writable. On success, buf is either left\n *            untouched, or it is unreferenced and a new writable AVBufferRef is\n *            written in its place. On failure, buf is left untouched.\n * @return 0 on success, a negative AVERROR on failure.\n */\nint av_buffer_make_writable(AVBufferRef **buf);\n\n/**\n * Reallocate a given buffer.\n *\n * @param buf  a buffer reference to reallocate. On success, buf will be\n *             unreferenced and a new reference with the required size will be\n *             written in its place. On failure buf will be left untouched. *buf\n *             may be NULL, then a new buffer is allocated.\n * @param size required new buffer size.\n * @return 0 on success, a negative AVERROR on failure.\n *\n * @note the buffer is actually reallocated with av_realloc() only if it was\n * initially allocated through av_buffer_realloc(NULL) and there is only one\n * reference to it (i.e. the one passed to this function). In all other cases\n * a new buffer is allocated and the data is copied.\n */\nint av_buffer_realloc(AVBufferRef **buf, size_t size);\n\n/**\n * Ensure dst refers to the same data as src.\n *\n * When *dst is already equivalent to src, do nothing. Otherwise unreference dst\n * and replace it with a new reference to src.\n *\n * @param dst Pointer to either a valid buffer reference or NULL. On success,\n *            this will point to a buffer reference equivalent to src. On\n *            failure, dst will be left untouched.\n * @param src A buffer reference to replace dst with. May be NULL, then this\n *            function is equivalent to av_buffer_unref(dst).\n * @return 0 on success\n *         AVERROR(ENOMEM) on memory allocation failure.\n */\nint av_buffer_replace(AVBufferRef **dst, const AVBufferRef *src);\n\n/**\n * @}\n */\n\n/**\n * @defgroup lavu_bufferpool AVBufferPool\n * @ingroup lavu_data\n *\n * @{\n * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers.\n *\n * Frequently allocating and freeing large buffers may be slow. AVBufferPool is\n * meant to solve this in cases when the caller needs a set of buffers of the\n * same size (the most obvious use case being buffers for raw video or audio\n * frames).\n *\n * At the beginning, the user must call av_buffer_pool_init() to create the\n * buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to\n * get a reference to a new buffer, similar to av_buffer_alloc(). This new\n * reference works in all aspects the same way as the one created by\n * av_buffer_alloc(). However, when the last reference to this buffer is\n * unreferenced, it is returned to the pool instead of being freed and will be\n * reused for subsequent av_buffer_pool_get() calls.\n *\n * When the caller is done with the pool and no longer needs to allocate any new\n * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable.\n * Once all the buffers are released, it will automatically be freed.\n *\n * Allocating and releasing buffers with this API is thread-safe as long as\n * either the default alloc callback is used, or the user-supplied one is\n * thread-safe.\n */\n\n/**\n * The buffer pool. This structure is opaque and not meant to be accessed\n * directly. It is allocated with av_buffer_pool_init() and freed with\n * av_buffer_pool_uninit().\n */\ntypedef struct AVBufferPool AVBufferPool;\n\n/**\n * Allocate and initialize a buffer pool.\n *\n * @param size size of each buffer in this pool\n * @param alloc a function that will be used to allocate new buffers when the\n * pool is empty. May be NULL, then the default allocator will be used\n * (av_buffer_alloc()).\n * @return newly created buffer pool on success, NULL on error.\n */\nAVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size));\n\n/**\n * Allocate and initialize a buffer pool with a more complex allocator.\n *\n * @param size size of each buffer in this pool\n * @param opaque arbitrary user data used by the allocator\n * @param alloc a function that will be used to allocate new buffers when the\n *              pool is empty. May be NULL, then the default allocator will be\n *              used (av_buffer_alloc()).\n * @param pool_free a function that will be called immediately before the pool\n *                  is freed. I.e. after av_buffer_pool_uninit() is called\n *                  by the caller and all the frames are returned to the pool\n *                  and freed. It is intended to uninitialize the user opaque\n *                  data. May be NULL.\n * @return newly created buffer pool on success, NULL on error.\n */\nAVBufferPool *av_buffer_pool_init2(size_t size, void *opaque,\n                                   AVBufferRef* (*alloc)(void *opaque, size_t size),\n                                   void (*pool_free)(void *opaque));\n\n/**\n * Mark the pool as being available for freeing. It will actually be freed only\n * once all the allocated buffers associated with the pool are released. Thus it\n * is safe to call this function while some of the allocated buffers are still\n * in use.\n *\n * @param pool pointer to the pool to be freed. It will be set to NULL.\n */\nvoid av_buffer_pool_uninit(AVBufferPool **pool);\n\n/**\n * Allocate a new AVBuffer, reusing an old buffer from the pool when available.\n * This function may be called simultaneously from multiple threads.\n *\n * @return a reference to the new buffer on success, NULL on error.\n */\nAVBufferRef *av_buffer_pool_get(AVBufferPool *pool);\n\n/**\n * Query the original opaque parameter of an allocated buffer in the pool.\n *\n * @param ref a buffer reference to a buffer returned by av_buffer_pool_get.\n * @return the opaque parameter set by the buffer allocator function of the\n *         buffer pool.\n *\n * @note the opaque parameter of ref is used by the buffer pool implementation,\n * therefore you have to use this function to access the original opaque\n * parameter of an allocated buffer.\n */\nvoid *av_buffer_pool_buffer_get_opaque(const AVBufferRef *ref);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_BUFFER_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/camellia.h",
    "content": "/*\n * An implementation of the CAMELLIA algorithm as mentioned in RFC3713\n * Copyright (c) 2014 Supraja Meedinti\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_CAMELLIA_H\n#define AVUTIL_CAMELLIA_H\n\n#include <stdint.h>\n\n\n/**\n  * @file\n  * @brief Public header for libavutil CAMELLIA algorithm\n  * @defgroup lavu_camellia CAMELLIA\n  * @ingroup lavu_crypto\n  * @{\n  */\n\nextern const int av_camellia_size;\n\nstruct AVCAMELLIA;\n\n/**\n  * Allocate an AVCAMELLIA context\n  * To free the struct: av_free(ptr)\n  */\nstruct AVCAMELLIA *av_camellia_alloc(void);\n\n/**\n  * Initialize an AVCAMELLIA context.\n  *\n  * @param ctx an AVCAMELLIA context\n  * @param key a key of 16, 24, 32 bytes used for encryption/decryption\n  * @param key_bits number of keybits: possible are 128, 192, 256\n */\nint av_camellia_init(struct AVCAMELLIA *ctx, const uint8_t *key, int key_bits);\n\n/**\n  * Encrypt or decrypt a buffer using a previously initialized context\n  *\n  * @param ctx an AVCAMELLIA context\n  * @param dst destination array, can be equal to src\n  * @param src source array, can be equal to dst\n  * @param count number of 16 byte blocks\n  * @paran iv initialization vector for CBC mode, NULL for ECB mode\n  * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_camellia_crypt(struct AVCAMELLIA *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t* iv, int decrypt);\n\n/**\n * @}\n */\n#endif /* AVUTIL_CAMELLIA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/cast5.h",
    "content": "/*\n * An implementation of the CAST128 algorithm as mentioned in RFC2144\n * Copyright (c) 2014 Supraja Meedinti\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_CAST5_H\n#define AVUTIL_CAST5_H\n\n#include <stdint.h>\n\n\n/**\n  * @file\n  * @brief Public header for libavutil CAST5 algorithm\n  * @defgroup lavu_cast5 CAST5\n  * @ingroup lavu_crypto\n  * @{\n  */\n\nextern const int av_cast5_size;\n\nstruct AVCAST5;\n\n/**\n  * Allocate an AVCAST5 context\n  * To free the struct: av_free(ptr)\n  */\nstruct AVCAST5 *av_cast5_alloc(void);\n/**\n  * Initialize an AVCAST5 context.\n  *\n  * @param ctx an AVCAST5 context\n  * @param key a key of 5,6,...16 bytes used for encryption/decryption\n  * @param key_bits number of keybits: possible are 40,48,...,128\n  * @return 0 on success, less than 0 on failure\n */\nint av_cast5_init(struct AVCAST5 *ctx, const uint8_t *key, int key_bits);\n\n/**\n  * Encrypt or decrypt a buffer using a previously initialized context, ECB mode only\n  *\n  * @param ctx an AVCAST5 context\n  * @param dst destination array, can be equal to src\n  * @param src source array, can be equal to dst\n  * @param count number of 8 byte blocks\n  * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_cast5_crypt(struct AVCAST5 *ctx, uint8_t *dst, const uint8_t *src, int count, int decrypt);\n\n/**\n  * Encrypt or decrypt a buffer using a previously initialized context\n  *\n  * @param ctx an AVCAST5 context\n  * @param dst destination array, can be equal to src\n  * @param src source array, can be equal to dst\n  * @param count number of 8 byte blocks\n  * @param iv initialization vector for CBC mode, NULL for ECB mode\n  * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_cast5_crypt2(struct AVCAST5 *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);\n/**\n * @}\n */\n#endif /* AVUTIL_CAST5_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/channel_layout.h",
    "content": "/*\n * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n * Copyright (c) 2008 Peter Ross\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_CHANNEL_LAYOUT_H\n#define AVUTIL_CHANNEL_LAYOUT_H\n\n#include <stdint.h>\n#include <stdlib.h>\n\n#include \"version.h\"\n#include \"attributes.h\"\n\n/**\n * @file\n * audio channel layout utility functions\n */\n\n/**\n * @addtogroup lavu_audio\n * @{\n */\n\nenum AVChannel {\n    ///< Invalid channel index\n    AV_CHAN_NONE = -1,\n    AV_CHAN_FRONT_LEFT,\n    AV_CHAN_FRONT_RIGHT,\n    AV_CHAN_FRONT_CENTER,\n    AV_CHAN_LOW_FREQUENCY,\n    AV_CHAN_BACK_LEFT,\n    AV_CHAN_BACK_RIGHT,\n    AV_CHAN_FRONT_LEFT_OF_CENTER,\n    AV_CHAN_FRONT_RIGHT_OF_CENTER,\n    AV_CHAN_BACK_CENTER,\n    AV_CHAN_SIDE_LEFT,\n    AV_CHAN_SIDE_RIGHT,\n    AV_CHAN_TOP_CENTER,\n    AV_CHAN_TOP_FRONT_LEFT,\n    AV_CHAN_TOP_FRONT_CENTER,\n    AV_CHAN_TOP_FRONT_RIGHT,\n    AV_CHAN_TOP_BACK_LEFT,\n    AV_CHAN_TOP_BACK_CENTER,\n    AV_CHAN_TOP_BACK_RIGHT,\n    /** Stereo downmix. */\n    AV_CHAN_STEREO_LEFT = 29,\n    /** See above. */\n    AV_CHAN_STEREO_RIGHT,\n    AV_CHAN_WIDE_LEFT,\n    AV_CHAN_WIDE_RIGHT,\n    AV_CHAN_SURROUND_DIRECT_LEFT,\n    AV_CHAN_SURROUND_DIRECT_RIGHT,\n    AV_CHAN_LOW_FREQUENCY_2,\n    AV_CHAN_TOP_SIDE_LEFT,\n    AV_CHAN_TOP_SIDE_RIGHT,\n    AV_CHAN_BOTTOM_FRONT_CENTER,\n    AV_CHAN_BOTTOM_FRONT_LEFT,\n    AV_CHAN_BOTTOM_FRONT_RIGHT,\n\n    /** Channel is empty can be safely skipped. */\n    AV_CHAN_UNUSED = 0x200,\n\n    /** Channel contains data, but its position is unknown. */\n    AV_CHAN_UNKNOWN = 0x300,\n\n    /**\n     * Range of channels between AV_CHAN_AMBISONIC_BASE and\n     * AV_CHAN_AMBISONIC_END represent Ambisonic components using the ACN system.\n     *\n     * Given a channel id <i> between AV_CHAN_AMBISONIC_BASE and\n     * AV_CHAN_AMBISONIC_END (inclusive), the ACN index of the channel <n> is\n     * <n> = <i> - AV_CHAN_AMBISONIC_BASE.\n     *\n     * @note these values are only used for AV_CHANNEL_ORDER_CUSTOM channel\n     * orderings, the AV_CHANNEL_ORDER_AMBISONIC ordering orders the channels\n     * implicitly by their position in the stream.\n     */\n    AV_CHAN_AMBISONIC_BASE = 0x400,\n    // leave space for 1024 ids, which correspond to maximum order-32 harmonics,\n    // which should be enough for the foreseeable use cases\n    AV_CHAN_AMBISONIC_END  = 0x7ff,\n};\n\nenum AVChannelOrder {\n    /**\n     * Only the channel count is specified, without any further information\n     * about the channel order.\n     */\n    AV_CHANNEL_ORDER_UNSPEC,\n    /**\n     * The native channel order, i.e. the channels are in the same order in\n     * which they are defined in the AVChannel enum. This supports up to 63\n     * different channels.\n     */\n    AV_CHANNEL_ORDER_NATIVE,\n    /**\n     * The channel order does not correspond to any other predefined order and\n     * is stored as an explicit map. For example, this could be used to support\n     * layouts with 64 or more channels, or with empty/skipped (AV_CHAN_SILENCE)\n     * channels at arbitrary positions.\n     */\n    AV_CHANNEL_ORDER_CUSTOM,\n    /**\n     * The audio is represented as the decomposition of the sound field into\n     * spherical harmonics. Each channel corresponds to a single expansion\n     * component. Channels are ordered according to ACN (Ambisonic Channel\n     * Number).\n     *\n     * The channel with the index n in the stream contains the spherical\n     * harmonic of degree l and order m given by\n     * @code{.unparsed}\n     *   l   = floor(sqrt(n)),\n     *   m   = n - l * (l + 1).\n     * @endcode\n     *\n     * Conversely given a spherical harmonic of degree l and order m, the\n     * corresponding channel index n is given by\n     * @code{.unparsed}\n     *   n = l * (l + 1) + m.\n     * @endcode\n     *\n     * Normalization is assumed to be SN3D (Schmidt Semi-Normalization)\n     * as defined in AmbiX format $ 2.1.\n     */\n    AV_CHANNEL_ORDER_AMBISONIC,\n};\n\n\n/**\n * @defgroup channel_masks Audio channel masks\n *\n * A channel layout is a 64-bits integer with a bit set for every channel.\n * The number of bits set must be equal to the number of channels.\n * The value 0 means that the channel layout is not known.\n * @note this data structure is not powerful enough to handle channels\n * combinations that have the same channel multiple times, such as\n * dual-mono.\n *\n * @{\n */\n#define AV_CH_FRONT_LEFT             (1ULL << AV_CHAN_FRONT_LEFT           )\n#define AV_CH_FRONT_RIGHT            (1ULL << AV_CHAN_FRONT_RIGHT          )\n#define AV_CH_FRONT_CENTER           (1ULL << AV_CHAN_FRONT_CENTER         )\n#define AV_CH_LOW_FREQUENCY          (1ULL << AV_CHAN_LOW_FREQUENCY        )\n#define AV_CH_BACK_LEFT              (1ULL << AV_CHAN_BACK_LEFT            )\n#define AV_CH_BACK_RIGHT             (1ULL << AV_CHAN_BACK_RIGHT           )\n#define AV_CH_FRONT_LEFT_OF_CENTER   (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER )\n#define AV_CH_FRONT_RIGHT_OF_CENTER  (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER)\n#define AV_CH_BACK_CENTER            (1ULL << AV_CHAN_BACK_CENTER          )\n#define AV_CH_SIDE_LEFT              (1ULL << AV_CHAN_SIDE_LEFT            )\n#define AV_CH_SIDE_RIGHT             (1ULL << AV_CHAN_SIDE_RIGHT           )\n#define AV_CH_TOP_CENTER             (1ULL << AV_CHAN_TOP_CENTER           )\n#define AV_CH_TOP_FRONT_LEFT         (1ULL << AV_CHAN_TOP_FRONT_LEFT       )\n#define AV_CH_TOP_FRONT_CENTER       (1ULL << AV_CHAN_TOP_FRONT_CENTER     )\n#define AV_CH_TOP_FRONT_RIGHT        (1ULL << AV_CHAN_TOP_FRONT_RIGHT      )\n#define AV_CH_TOP_BACK_LEFT          (1ULL << AV_CHAN_TOP_BACK_LEFT        )\n#define AV_CH_TOP_BACK_CENTER        (1ULL << AV_CHAN_TOP_BACK_CENTER      )\n#define AV_CH_TOP_BACK_RIGHT         (1ULL << AV_CHAN_TOP_BACK_RIGHT       )\n#define AV_CH_STEREO_LEFT            (1ULL << AV_CHAN_STEREO_LEFT          )\n#define AV_CH_STEREO_RIGHT           (1ULL << AV_CHAN_STEREO_RIGHT         )\n#define AV_CH_WIDE_LEFT              (1ULL << AV_CHAN_WIDE_LEFT            )\n#define AV_CH_WIDE_RIGHT             (1ULL << AV_CHAN_WIDE_RIGHT           )\n#define AV_CH_SURROUND_DIRECT_LEFT   (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT )\n#define AV_CH_SURROUND_DIRECT_RIGHT  (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT)\n#define AV_CH_LOW_FREQUENCY_2        (1ULL << AV_CHAN_LOW_FREQUENCY_2      )\n#define AV_CH_TOP_SIDE_LEFT          (1ULL << AV_CHAN_TOP_SIDE_LEFT        )\n#define AV_CH_TOP_SIDE_RIGHT         (1ULL << AV_CHAN_TOP_SIDE_RIGHT       )\n#define AV_CH_BOTTOM_FRONT_CENTER    (1ULL << AV_CHAN_BOTTOM_FRONT_CENTER  )\n#define AV_CH_BOTTOM_FRONT_LEFT      (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT    )\n#define AV_CH_BOTTOM_FRONT_RIGHT     (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT   )\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n/** Channel mask value used for AVCodecContext.request_channel_layout\n    to indicate that the user requests the channel order of the decoder output\n    to be the native codec channel order.\n    @deprecated channel order is now indicated in a special field in\n                AVChannelLayout\n    */\n#define AV_CH_LAYOUT_NATIVE          0x8000000000000000ULL\n#endif\n\n/**\n * @}\n * @defgroup channel_mask_c Audio channel layouts\n * @{\n * */\n#define AV_CH_LAYOUT_MONO              (AV_CH_FRONT_CENTER)\n#define AV_CH_LAYOUT_STEREO            (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)\n#define AV_CH_LAYOUT_2POINT1           (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY)\n#define AV_CH_LAYOUT_2_1               (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)\n#define AV_CH_LAYOUT_SURROUND          (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)\n#define AV_CH_LAYOUT_3POINT1           (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY)\n#define AV_CH_LAYOUT_4POINT0           (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER)\n#define AV_CH_LAYOUT_4POINT1           (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY)\n#define AV_CH_LAYOUT_2_2               (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)\n#define AV_CH_LAYOUT_QUAD              (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)\n#define AV_CH_LAYOUT_5POINT0           (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)\n#define AV_CH_LAYOUT_5POINT1           (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY)\n#define AV_CH_LAYOUT_5POINT0_BACK      (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)\n#define AV_CH_LAYOUT_5POINT1_BACK      (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY)\n#define AV_CH_LAYOUT_6POINT0           (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER)\n#define AV_CH_LAYOUT_6POINT0_FRONT     (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)\n#define AV_CH_LAYOUT_HEXAGONAL         (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER)\n#define AV_CH_LAYOUT_6POINT1           (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER)\n#define AV_CH_LAYOUT_6POINT1_BACK      (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER)\n#define AV_CH_LAYOUT_6POINT1_FRONT     (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY)\n#define AV_CH_LAYOUT_7POINT0           (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)\n#define AV_CH_LAYOUT_7POINT0_FRONT     (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)\n#define AV_CH_LAYOUT_7POINT1           (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)\n#define AV_CH_LAYOUT_7POINT1_WIDE      (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)\n#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)\n#define AV_CH_LAYOUT_OCTAGONAL         (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT)\n#define AV_CH_LAYOUT_HEXADECAGONAL     (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT)\n#define AV_CH_LAYOUT_STEREO_DOWNMIX    (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT)\n#define AV_CH_LAYOUT_22POINT2          (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER|AV_CH_BACK_CENTER|AV_CH_LOW_FREQUENCY_2|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_CENTER|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_BOTTOM_FRONT_CENTER|AV_CH_BOTTOM_FRONT_LEFT|AV_CH_BOTTOM_FRONT_RIGHT)\n\nenum AVMatrixEncoding {\n    AV_MATRIX_ENCODING_NONE,\n    AV_MATRIX_ENCODING_DOLBY,\n    AV_MATRIX_ENCODING_DPLII,\n    AV_MATRIX_ENCODING_DPLIIX,\n    AV_MATRIX_ENCODING_DPLIIZ,\n    AV_MATRIX_ENCODING_DOLBYEX,\n    AV_MATRIX_ENCODING_DOLBYHEADPHONE,\n    AV_MATRIX_ENCODING_NB\n};\n\n/**\n * @}\n */\n\n/**\n * An AVChannelCustom defines a single channel within a custom order layout\n *\n * Unlike most structures in FFmpeg, sizeof(AVChannelCustom) is a part of the\n * public ABI.\n *\n * No new fields may be added to it without a major version bump.\n */\ntypedef struct AVChannelCustom {\n    enum AVChannel id;\n    char name[16];\n    void *opaque;\n} AVChannelCustom;\n\n/**\n * An AVChannelLayout holds information about the channel layout of audio data.\n *\n * A channel layout here is defined as a set of channels ordered in a specific\n * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an\n * AVChannelLayout carries only the channel count).\n *\n * Unlike most structures in Libav, sizeof(AVChannelLayout) is a part of the\n * public ABI and may be used by the caller. E.g. it may be allocated on stack\n * or embedded in caller-defined structs.\n *\n * AVChannelLayout can be initialized as follows:\n * - default initialization with {0}, followed by setting all used fields\n *   correctly;\n * - by assigning one of the predefined AV_CHANNEL_LAYOUT_* initializers;\n * - with a constructor function, such as av_channel_layout_default(),\n *   av_channel_layout_from_mask() or av_channel_layout_from_string().\n *\n * The channel layout must be unitialized with av_channel_layout_uninit()\n *\n * Copying an AVChannelLayout via assigning is forbidden,\n * av_channel_layout_copy() must be used instead (and its return value should\n * be checked)\n *\n * No new fields may be added to it without a major version bump, except for\n * new elements of the union fitting in sizeof(uint64_t).\n */\ntypedef struct AVChannelLayout {\n    /**\n     * Channel order used in this layout.\n     * This is a mandatory field.\n     */\n    enum AVChannelOrder order;\n\n    /**\n     * Number of channels in this layout. Mandatory field.\n     */\n    int nb_channels;\n\n    /**\n     * Details about which channels are present in this layout.\n     * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be\n     * used.\n     */\n    union {\n        /**\n         * This member must be used for AV_CHANNEL_ORDER_NATIVE, and may be used\n         * for AV_CHANNEL_ORDER_AMBISONIC to signal non-diegetic channels.\n         * It is a bitmask, where the position of each set bit means that the\n         * AVChannel with the corresponding value is present.\n         *\n         * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO\n         * is present in the layout. Otherwise it is not present.\n         *\n         * @note when a channel layout using a bitmask is constructed or\n         * modified manually (i.e.  not using any of the av_channel_layout_*\n         * functions), the code doing it must ensure that the number of set bits\n         * is equal to nb_channels.\n         */\n        uint64_t mask;\n        /**\n         * This member must be used when the channel order is\n         * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each\n         * element signalling the presence of the AVChannel with the\n         * corresponding value in map[i].id.\n         *\n         * I.e. when map[i].id is equal to AV_CHAN_FOO, then AV_CH_FOO is the\n         * i-th channel in the audio data.\n         *\n         * When map[i].id is in the range between AV_CHAN_AMBISONIC_BASE and\n         * AV_CHAN_AMBISONIC_END (inclusive), the channel contains an ambisonic\n         * component with ACN index (as defined above)\n         * n = map[i].id - AV_CHAN_AMBISONIC_BASE.\n         *\n         * map[i].name may be filled with a 0-terminated string, in which case\n         * it will be used for the purpose of identifying the channel with the\n         * convenience functions below. Otherise it must be zeroed.\n         */\n        AVChannelCustom *map;\n    } u;\n\n    /**\n     * For some private data of the user.\n     */\n    void *opaque;\n} AVChannelLayout;\n\n#define AV_CHANNEL_LAYOUT_MASK(nb, m) \\\n    { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = (nb), .u = { .mask = (m) }}\n\n#define AV_CHANNEL_LAYOUT_MONO              AV_CHANNEL_LAYOUT_MASK(1,  AV_CH_LAYOUT_MONO)\n#define AV_CHANNEL_LAYOUT_STEREO            AV_CHANNEL_LAYOUT_MASK(2,  AV_CH_LAYOUT_STEREO)\n#define AV_CHANNEL_LAYOUT_2POINT1           AV_CHANNEL_LAYOUT_MASK(3,  AV_CH_LAYOUT_2POINT1)\n#define AV_CHANNEL_LAYOUT_2_1               AV_CHANNEL_LAYOUT_MASK(3,  AV_CH_LAYOUT_2_1)\n#define AV_CHANNEL_LAYOUT_SURROUND          AV_CHANNEL_LAYOUT_MASK(3,  AV_CH_LAYOUT_SURROUND)\n#define AV_CHANNEL_LAYOUT_3POINT1           AV_CHANNEL_LAYOUT_MASK(4,  AV_CH_LAYOUT_3POINT1)\n#define AV_CHANNEL_LAYOUT_4POINT0           AV_CHANNEL_LAYOUT_MASK(4,  AV_CH_LAYOUT_4POINT0)\n#define AV_CHANNEL_LAYOUT_4POINT1           AV_CHANNEL_LAYOUT_MASK(5,  AV_CH_LAYOUT_4POINT1)\n#define AV_CHANNEL_LAYOUT_2_2               AV_CHANNEL_LAYOUT_MASK(4,  AV_CH_LAYOUT_2_2)\n#define AV_CHANNEL_LAYOUT_QUAD              AV_CHANNEL_LAYOUT_MASK(4,  AV_CH_LAYOUT_QUAD)\n#define AV_CHANNEL_LAYOUT_5POINT0           AV_CHANNEL_LAYOUT_MASK(5,  AV_CH_LAYOUT_5POINT0)\n#define AV_CHANNEL_LAYOUT_5POINT1           AV_CHANNEL_LAYOUT_MASK(6,  AV_CH_LAYOUT_5POINT1)\n#define AV_CHANNEL_LAYOUT_5POINT0_BACK      AV_CHANNEL_LAYOUT_MASK(5,  AV_CH_LAYOUT_5POINT0_BACK)\n#define AV_CHANNEL_LAYOUT_5POINT1_BACK      AV_CHANNEL_LAYOUT_MASK(6,  AV_CH_LAYOUT_5POINT1_BACK)\n#define AV_CHANNEL_LAYOUT_6POINT0           AV_CHANNEL_LAYOUT_MASK(6,  AV_CH_LAYOUT_6POINT0)\n#define AV_CHANNEL_LAYOUT_6POINT0_FRONT     AV_CHANNEL_LAYOUT_MASK(6,  AV_CH_LAYOUT_6POINT0_FRONT)\n#define AV_CHANNEL_LAYOUT_HEXAGONAL         AV_CHANNEL_LAYOUT_MASK(6,  AV_CH_LAYOUT_HEXAGONAL)\n#define AV_CHANNEL_LAYOUT_6POINT1           AV_CHANNEL_LAYOUT_MASK(7,  AV_CH_LAYOUT_6POINT1)\n#define AV_CHANNEL_LAYOUT_6POINT1_BACK      AV_CHANNEL_LAYOUT_MASK(7,  AV_CH_LAYOUT_6POINT1_BACK)\n#define AV_CHANNEL_LAYOUT_6POINT1_FRONT     AV_CHANNEL_LAYOUT_MASK(7,  AV_CH_LAYOUT_6POINT1_FRONT)\n#define AV_CHANNEL_LAYOUT_7POINT0           AV_CHANNEL_LAYOUT_MASK(7,  AV_CH_LAYOUT_7POINT0)\n#define AV_CHANNEL_LAYOUT_7POINT0_FRONT     AV_CHANNEL_LAYOUT_MASK(7,  AV_CH_LAYOUT_7POINT0_FRONT)\n#define AV_CHANNEL_LAYOUT_7POINT1           AV_CHANNEL_LAYOUT_MASK(8,  AV_CH_LAYOUT_7POINT1)\n#define AV_CHANNEL_LAYOUT_7POINT1_WIDE      AV_CHANNEL_LAYOUT_MASK(8,  AV_CH_LAYOUT_7POINT1_WIDE)\n#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK AV_CHANNEL_LAYOUT_MASK(8,  AV_CH_LAYOUT_7POINT1_WIDE_BACK)\n#define AV_CHANNEL_LAYOUT_OCTAGONAL         AV_CHANNEL_LAYOUT_MASK(8,  AV_CH_LAYOUT_OCTAGONAL)\n#define AV_CHANNEL_LAYOUT_HEXADECAGONAL     AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL)\n#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX    AV_CHANNEL_LAYOUT_MASK(2,  AV_CH_LAYOUT_STEREO_DOWNMIX)\n#define AV_CHANNEL_LAYOUT_22POINT2          AV_CHANNEL_LAYOUT_MASK(24, AV_CH_LAYOUT_22POINT2)\n#define AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER \\\n    { .order = AV_CHANNEL_ORDER_AMBISONIC, .nb_channels = 4, .u = { .mask = 0 }}\n\nstruct AVBPrint;\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n/**\n * Return a channel layout id that matches name, or 0 if no match is found.\n *\n * name can be one or several of the following notations,\n * separated by '+' or '|':\n * - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0,\n *   5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix);\n * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC,\n *   SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR);\n * - a number of channels, in decimal, followed by 'c', yielding\n *   the default channel layout for that number of channels (@see\n *   av_get_default_channel_layout);\n * - a channel layout mask, in hexadecimal starting with \"0x\" (see the\n *   AV_CH_* macros).\n *\n * Example: \"stereo+FC\" = \"2c+FC\" = \"2c+1c\" = \"0x7\"\n *\n * @deprecated use av_channel_layout_from_string()\n */\nattribute_deprecated\nuint64_t av_get_channel_layout(const char *name);\n\n/**\n * Return a channel layout and the number of channels based on the specified name.\n *\n * This function is similar to (@see av_get_channel_layout), but can also parse\n * unknown channel layout specifications.\n *\n * @param[in]  name             channel layout specification string\n * @param[out] channel_layout   parsed channel layout (0 if unknown)\n * @param[out] nb_channels      number of channels\n *\n * @return 0 on success, AVERROR(EINVAL) if the parsing fails.\n * @deprecated use av_channel_layout_from_string()\n */\nattribute_deprecated\nint av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels);\n\n/**\n * Return a description of a channel layout.\n * If nb_channels is <= 0, it is guessed from the channel_layout.\n *\n * @param buf put here the string containing the channel layout\n * @param buf_size size in bytes of the buffer\n * @deprecated use av_channel_layout_describe()\n */\nattribute_deprecated\nvoid av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout);\n\n/**\n * Append a description of a channel layout to a bprint buffer.\n * @deprecated use av_channel_layout_describe()\n */\nattribute_deprecated\nvoid av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout);\n\n/**\n * Return the number of channels in the channel layout.\n * @deprecated use AVChannelLayout.nb_channels\n */\nattribute_deprecated\nint av_get_channel_layout_nb_channels(uint64_t channel_layout);\n\n/**\n * Return default channel layout for a given number of channels.\n *\n * @deprecated use av_channel_layout_default()\n */\nattribute_deprecated\nint64_t av_get_default_channel_layout(int nb_channels);\n\n/**\n * Get the index of a channel in channel_layout.\n *\n * @param channel a channel layout describing exactly one channel which must be\n *                present in channel_layout.\n *\n * @return index of channel in channel_layout on success, a negative AVERROR\n *         on error.\n *\n * @deprecated use av_channel_layout_index_from_channel()\n */\nattribute_deprecated\nint av_get_channel_layout_channel_index(uint64_t channel_layout,\n                                        uint64_t channel);\n\n/**\n * Get the channel with the given index in channel_layout.\n * @deprecated use av_channel_layout_channel_from_index()\n */\nattribute_deprecated\nuint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index);\n\n/**\n * Get the name of a given channel.\n *\n * @return channel name on success, NULL on error.\n *\n * @deprecated use av_channel_name()\n */\nattribute_deprecated\nconst char *av_get_channel_name(uint64_t channel);\n\n/**\n * Get the description of a given channel.\n *\n * @param channel  a channel layout with a single channel\n * @return  channel description on success, NULL on error\n * @deprecated use av_channel_description()\n */\nattribute_deprecated\nconst char *av_get_channel_description(uint64_t channel);\n\n/**\n * Get the value and name of a standard channel layout.\n *\n * @param[in]  index   index in an internal list, starting at 0\n * @param[out] layout  channel layout mask\n * @param[out] name    name of the layout\n * @return  0  if the layout exists,\n *          <0 if index is beyond the limits\n * @deprecated use av_channel_layout_standard()\n */\nattribute_deprecated\nint av_get_standard_channel_layout(unsigned index, uint64_t *layout,\n                                   const char **name);\n#endif\n\n/**\n * Get a human readable string in an abbreviated form describing a given channel.\n * This is the inverse function of @ref av_channel_from_string().\n *\n * @param buf pre-allocated buffer where to put the generated string\n * @param buf_size size in bytes of the buffer.\n * @return amount of bytes needed to hold the output string, or a negative AVERROR\n *         on failure. If the returned value is bigger than buf_size, then the\n *         string was truncated.\n */\nint av_channel_name(char *buf, size_t buf_size, enum AVChannel channel);\n\n/**\n * bprint variant of av_channel_name().\n *\n * @note the string will be appended to the bprint buffer.\n */\nvoid av_channel_name_bprint(struct AVBPrint *bp, enum AVChannel channel_id);\n\n/**\n * Get a human readable string describing a given channel.\n *\n * @param buf pre-allocated buffer where to put the generated string\n * @param buf_size size in bytes of the buffer.\n * @return amount of bytes needed to hold the output string, or a negative AVERROR\n *         on failure. If the returned value is bigger than buf_size, then the\n *         string was truncated.\n */\nint av_channel_description(char *buf, size_t buf_size, enum AVChannel channel);\n\n/**\n * bprint variant of av_channel_description().\n *\n * @note the string will be appended to the bprint buffer.\n */\nvoid av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id);\n\n/**\n * This is the inverse function of @ref av_channel_name().\n *\n * @return the channel with the given name\n *         AV_CHAN_NONE when name does not identify a known channel\n */\nenum AVChannel av_channel_from_string(const char *name);\n\n/**\n * Initialize a native channel layout from a bitmask indicating which channels\n * are present.\n *\n * @param channel_layout the layout structure to be initialized\n * @param mask bitmask describing the channel layout\n *\n * @return 0 on success\n *         AVERROR(EINVAL) for invalid mask values\n */\nint av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask);\n\n/**\n * Initialize a channel layout from a given string description.\n * The input string can be represented by:\n *  - the formal channel layout name (returned by av_channel_layout_describe())\n *  - single or multiple channel names (returned by av_channel_name(), eg. \"FL\",\n *    or concatenated with \"+\", each optionally containing a custom name after\n *    a \"@\", eg. \"FL@Left+FR@Right+LFE\")\n *  - a decimal or hexadecimal value of a native channel layout (eg. \"4\" or \"0x4\")\n *  - the number of channels with default layout (eg. \"4c\")\n *  - the number of unordered channels (eg. \"4C\" or \"4 channels\")\n *  - the ambisonic order followed by optional non-diegetic channels (eg.\n *    \"ambisonic 2+stereo\")\n *\n * @param channel_layout input channel layout\n * @param str string describing the channel layout\n * @return 0 channel layout was detected, AVERROR_INVALIDATATA otherwise\n */\nint av_channel_layout_from_string(AVChannelLayout *channel_layout,\n                                  const char *str);\n\n/**\n * Get the default channel layout for a given number of channels.\n *\n * @param channel_layout the layout structure to be initialized\n * @param nb_channels number of channels\n */\nvoid av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels);\n\n/**\n * Iterate over all standard channel layouts.\n *\n * @param opaque a pointer where libavutil will store the iteration state. Must\n *               point to NULL to start the iteration.\n *\n * @return the standard channel layout or NULL when the iteration is\n *         finished\n */\nconst AVChannelLayout *av_channel_layout_standard(void **opaque);\n\n/**\n * Free any allocated data in the channel layout and reset the channel\n * count to 0.\n *\n * @param channel_layout the layout structure to be uninitialized\n */\nvoid av_channel_layout_uninit(AVChannelLayout *channel_layout);\n\n/**\n * Make a copy of a channel layout. This differs from just assigning src to dst\n * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.\n *\n * @note the destination channel_layout will be always uninitialized before copy.\n *\n * @param dst destination channel layout\n * @param src source channel layout\n * @return 0 on success, a negative AVERROR on error.\n */\nint av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src);\n\n/**\n * Get a human-readable string describing the channel layout properties.\n * The string will be in the same format that is accepted by\n * @ref av_channel_layout_from_string(), allowing to rebuild the same\n * channel layout, except for opaque pointers.\n *\n * @param channel_layout channel layout to be described\n * @param buf pre-allocated buffer where to put the generated string\n * @param buf_size size in bytes of the buffer.\n * @return amount of bytes needed to hold the output string, or a negative AVERROR\n *         on failure. If the returned value is bigger than buf_size, then the\n *         string was truncated.\n */\nint av_channel_layout_describe(const AVChannelLayout *channel_layout,\n                               char *buf, size_t buf_size);\n\n/**\n * bprint variant of av_channel_layout_describe().\n *\n * @note the string will be appended to the bprint buffer.\n * @return 0 on success, or a negative AVERROR value on failure.\n */\nint av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout,\n                                      struct AVBPrint *bp);\n\n/**\n * Get the channel with the given index in a channel layout.\n *\n * @param channel_layout input channel layout\n * @return channel with the index idx in channel_layout on success or\n *         AV_CHAN_NONE on failure (if idx is not valid or the channel order is\n *         unspecified)\n */\nenum AVChannel\nav_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx);\n\n/**\n * Get the index of a given channel in a channel layout. In case multiple\n * channels are found, only the first match will be returned.\n *\n * @param channel_layout input channel layout\n * @return index of channel in channel_layout on success or a negative number if\n *         channel is not present in channel_layout.\n */\nint av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout,\n                                         enum AVChannel channel);\n\n/**\n * Get the index in a channel layout of a channel described by the given string.\n * In case multiple channels are found, only the first match will be returned.\n *\n * This function accepts channel names in the same format as\n * @ref av_channel_from_string().\n *\n * @param channel_layout input channel layout\n * @return a channel index described by the given string, or a negative AVERROR\n *         value.\n */\nint av_channel_layout_index_from_string(const AVChannelLayout *channel_layout,\n                                        const char *name);\n\n/**\n * Get a channel described by the given string.\n *\n * This function accepts channel names in the same format as\n * @ref av_channel_from_string().\n *\n * @param channel_layout input channel layout\n * @return a channel described by the given string in channel_layout on success\n *         or AV_CHAN_NONE on failure (if the string is not valid or the channel\n *         order is unspecified)\n */\nenum AVChannel\nav_channel_layout_channel_from_string(const AVChannelLayout *channel_layout,\n                                      const char *name);\n\n/**\n * Find out what channels from a given set are present in a channel layout,\n * without regard for their positions.\n *\n * @param channel_layout input channel layout\n * @param mask a combination of AV_CH_* representing a set of channels\n * @return a bitfield representing all the channels from mask that are present\n *         in channel_layout\n */\nuint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout,\n                                  uint64_t mask);\n\n/**\n * Check whether a channel layout is valid, i.e. can possibly describe audio\n * data.\n *\n * @param channel_layout input channel layout\n * @return 1 if channel_layout is valid, 0 otherwise.\n */\nint av_channel_layout_check(const AVChannelLayout *channel_layout);\n\n/**\n * Check whether two channel layouts are semantically the same, i.e. the same\n * channels are present on the same positions in both.\n *\n * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is\n * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC,\n * they are considered equal iff the channel counts are the same in both.\n *\n * @param chl input channel layout\n * @param chl1 input channel layout\n * @return 0 if chl and chl1 are equal, 1 if they are not equal. A negative\n *         AVERROR code if one or both are invalid.\n */\nint av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1);\n\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_CHANNEL_LAYOUT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/common.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * common internal and external API header\n */\n\n#ifndef AVUTIL_COMMON_H\n#define AVUTIL_COMMON_H\n\n#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C)\n#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS\n#endif\n\n#include <errno.h>\n#include <inttypes.h>\n#include <limits.h>\n#include <math.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"attributes.h\"\n#include \"macros.h\"\n\n//rounded division & shift\n#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))\n/* assume b>0 */\n#define ROUNDED_DIV(a,b) (((a)>=0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))\n/* Fast a/(1<<b) rounded toward +inf. Assume a>=0 and b>=0 */\n#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \\\n                                                       : ((a) + (1<<(b)) - 1) >> (b))\n/* Backwards compat. */\n#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT\n\n#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b))\n#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b))\n\n/**\n * Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they\n * are not representable as absolute values of their type. This is the same\n * as with *abs()\n * @see FFNABS()\n */\n#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))\n#define FFSIGN(a) ((a) > 0 ? 1 : -1)\n\n/**\n * Negative Absolute value.\n * this works for all integers of all types.\n * As with many macros, this evaluates its argument twice, it thus must not have\n * a sideeffect, that is FFNABS(x++) has undefined behavior.\n */\n#define FFNABS(a) ((a) <= 0 ? (a) : (-(a)))\n\n/**\n * Unsigned Absolute value.\n * This takes the absolute value of a signed int and returns it as a unsigned.\n * This also works with INT_MIN which would otherwise not be representable\n * As with many macros, this evaluates its argument twice.\n */\n#define FFABSU(a) ((a) <= 0 ? -(unsigned)(a) : (unsigned)(a))\n#define FFABS64U(a) ((a) <= 0 ? -(uint64_t)(a) : (uint64_t)(a))\n\n/* misc math functions */\n\n#ifdef HAVE_AV_CONFIG_H\n#   include \"config.h\"\n#   include \"intmath.h\"\n#endif\n\n#ifndef av_ceil_log2\n#   define av_ceil_log2     av_ceil_log2_c\n#endif\n#ifndef av_clip\n#   define av_clip          av_clip_c\n#endif\n#ifndef av_clip64\n#   define av_clip64        av_clip64_c\n#endif\n#ifndef av_clip_uint8\n#   define av_clip_uint8    av_clip_uint8_c\n#endif\n#ifndef av_clip_int8\n#   define av_clip_int8     av_clip_int8_c\n#endif\n#ifndef av_clip_uint16\n#   define av_clip_uint16   av_clip_uint16_c\n#endif\n#ifndef av_clip_int16\n#   define av_clip_int16    av_clip_int16_c\n#endif\n#ifndef av_clipl_int32\n#   define av_clipl_int32   av_clipl_int32_c\n#endif\n#ifndef av_clip_intp2\n#   define av_clip_intp2    av_clip_intp2_c\n#endif\n#ifndef av_clip_uintp2\n#   define av_clip_uintp2   av_clip_uintp2_c\n#endif\n#ifndef av_mod_uintp2\n#   define av_mod_uintp2    av_mod_uintp2_c\n#endif\n#ifndef av_sat_add32\n#   define av_sat_add32     av_sat_add32_c\n#endif\n#ifndef av_sat_dadd32\n#   define av_sat_dadd32    av_sat_dadd32_c\n#endif\n#ifndef av_sat_sub32\n#   define av_sat_sub32     av_sat_sub32_c\n#endif\n#ifndef av_sat_dsub32\n#   define av_sat_dsub32    av_sat_dsub32_c\n#endif\n#ifndef av_sat_add64\n#   define av_sat_add64     av_sat_add64_c\n#endif\n#ifndef av_sat_sub64\n#   define av_sat_sub64     av_sat_sub64_c\n#endif\n#ifndef av_clipf\n#   define av_clipf         av_clipf_c\n#endif\n#ifndef av_clipd\n#   define av_clipd         av_clipd_c\n#endif\n#ifndef av_popcount\n#   define av_popcount      av_popcount_c\n#endif\n#ifndef av_popcount64\n#   define av_popcount64    av_popcount64_c\n#endif\n#ifndef av_parity\n#   define av_parity        av_parity_c\n#endif\n\n#ifndef av_log2\nav_const int av_log2(unsigned v);\n#endif\n\n#ifndef av_log2_16bit\nav_const int av_log2_16bit(unsigned v);\n#endif\n\n/**\n * Clip a signed integer value into the amin-amax range.\n * @param a value to clip\n * @param amin minimum value of the clip range\n * @param amax maximum value of the clip range\n * @return clipped value\n */\nstatic av_always_inline av_const int av_clip_c(int a, int amin, int amax)\n{\n#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2\n    if (amin > amax) abort();\n#endif\n    if      (a < amin) return amin;\n    else if (a > amax) return amax;\n    else               return a;\n}\n\n/**\n * Clip a signed 64bit integer value into the amin-amax range.\n * @param a value to clip\n * @param amin minimum value of the clip range\n * @param amax maximum value of the clip range\n * @return clipped value\n */\nstatic av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax)\n{\n#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2\n    if (amin > amax) abort();\n#endif\n    if      (a < amin) return amin;\n    else if (a > amax) return amax;\n    else               return a;\n}\n\n/**\n * Clip a signed integer value into the 0-255 range.\n * @param a value to clip\n * @return clipped value\n */\nstatic av_always_inline av_const uint8_t av_clip_uint8_c(int a)\n{\n    if (a&(~0xFF)) return (~a)>>31;\n    else           return a;\n}\n\n/**\n * Clip a signed integer value into the -128,127 range.\n * @param a value to clip\n * @return clipped value\n */\nstatic av_always_inline av_const int8_t av_clip_int8_c(int a)\n{\n    if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F;\n    else                  return a;\n}\n\n/**\n * Clip a signed integer value into the 0-65535 range.\n * @param a value to clip\n * @return clipped value\n */\nstatic av_always_inline av_const uint16_t av_clip_uint16_c(int a)\n{\n    if (a&(~0xFFFF)) return (~a)>>31;\n    else             return a;\n}\n\n/**\n * Clip a signed integer value into the -32768,32767 range.\n * @param a value to clip\n * @return clipped value\n */\nstatic av_always_inline av_const int16_t av_clip_int16_c(int a)\n{\n    if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF;\n    else                      return a;\n}\n\n/**\n * Clip a signed 64-bit integer value into the -2147483648,2147483647 range.\n * @param a value to clip\n * @return clipped value\n */\nstatic av_always_inline av_const int32_t av_clipl_int32_c(int64_t a)\n{\n    if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF);\n    else                                         return (int32_t)a;\n}\n\n/**\n * Clip a signed integer into the -(2^p),(2^p-1) range.\n * @param  a value to clip\n * @param  p bit position to clip at\n * @return clipped value\n */\nstatic av_always_inline av_const int av_clip_intp2_c(int a, int p)\n{\n    if (((unsigned)a + (1 << p)) & ~((2 << p) - 1))\n        return (a >> 31) ^ ((1 << p) - 1);\n    else\n        return a;\n}\n\n/**\n * Clip a signed integer to an unsigned power of two range.\n * @param  a value to clip\n * @param  p bit position to clip at\n * @return clipped value\n */\nstatic av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p)\n{\n    if (a & ~((1<<p) - 1)) return (~a) >> 31 & ((1<<p) - 1);\n    else                   return  a;\n}\n\n/**\n * Clear high bits from an unsigned integer starting with specific bit position\n * @param  a value to clip\n * @param  p bit position to clip at\n * @return clipped value\n */\nstatic av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p)\n{\n    return a & ((1U << p) - 1);\n}\n\n/**\n * Add two signed 32-bit values with saturation.\n *\n * @param  a one value\n * @param  b another value\n * @return sum with signed saturation\n */\nstatic av_always_inline int av_sat_add32_c(int a, int b)\n{\n    return av_clipl_int32((int64_t)a + b);\n}\n\n/**\n * Add a doubled value to another value with saturation at both stages.\n *\n * @param  a first value\n * @param  b value doubled and added to a\n * @return sum sat(a + sat(2*b)) with signed saturation\n */\nstatic av_always_inline int av_sat_dadd32_c(int a, int b)\n{\n    return av_sat_add32(a, av_sat_add32(b, b));\n}\n\n/**\n * Subtract two signed 32-bit values with saturation.\n *\n * @param  a one value\n * @param  b another value\n * @return difference with signed saturation\n */\nstatic av_always_inline int av_sat_sub32_c(int a, int b)\n{\n    return av_clipl_int32((int64_t)a - b);\n}\n\n/**\n * Subtract a doubled value from another value with saturation at both stages.\n *\n * @param  a first value\n * @param  b value doubled and subtracted from a\n * @return difference sat(a - sat(2*b)) with signed saturation\n */\nstatic av_always_inline int av_sat_dsub32_c(int a, int b)\n{\n    return av_sat_sub32(a, av_sat_add32(b, b));\n}\n\n/**\n * Add two signed 64-bit values with saturation.\n *\n * @param  a one value\n * @param  b another value\n * @return sum with signed saturation\n */\nstatic av_always_inline int64_t av_sat_add64_c(int64_t a, int64_t b) {\n#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_add_overflow)\n    int64_t tmp;\n    return !__builtin_add_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN);\n#else\n    int64_t s = a+(uint64_t)b;\n    if ((int64_t)(a^b | ~s^b) >= 0)\n        return INT64_MAX ^ (b >> 63);\n    return s;\n#endif\n}\n\n/**\n * Subtract two signed 64-bit values with saturation.\n *\n * @param  a one value\n * @param  b another value\n * @return difference with signed saturation\n */\nstatic av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) {\n#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_sub_overflow)\n    int64_t tmp;\n    return !__builtin_sub_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN);\n#else\n    if (b <= 0 && a >= INT64_MAX + b)\n        return INT64_MAX;\n    if (b >= 0 && a <= INT64_MIN + b)\n        return INT64_MIN;\n    return a - b;\n#endif\n}\n\n/**\n * Clip a float value into the amin-amax range.\n * If a is nan or -inf amin will be returned.\n * If a is +inf amax will be returned.\n * @param a value to clip\n * @param amin minimum value of the clip range\n * @param amax maximum value of the clip range\n * @return clipped value\n */\nstatic av_always_inline av_const float av_clipf_c(float a, float amin, float amax)\n{\n#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2\n    if (amin > amax) abort();\n#endif\n    return FFMIN(FFMAX(a, amin), amax);\n}\n\n/**\n * Clip a double value into the amin-amax range.\n * If a is nan or -inf amin will be returned.\n * If a is +inf amax will be returned.\n * @param a value to clip\n * @param amin minimum value of the clip range\n * @param amax maximum value of the clip range\n * @return clipped value\n */\nstatic av_always_inline av_const double av_clipd_c(double a, double amin, double amax)\n{\n#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2\n    if (amin > amax) abort();\n#endif\n    return FFMIN(FFMAX(a, amin), amax);\n}\n\n/** Compute ceil(log2(x)).\n * @param x value used to compute ceil(log2(x))\n * @return computed ceiling of log2(x)\n */\nstatic av_always_inline av_const int av_ceil_log2_c(int x)\n{\n    return av_log2((x - 1U) << 1);\n}\n\n/**\n * Count number of bits set to one in x\n * @param x value to count bits of\n * @return the number of bits set to one in x\n */\nstatic av_always_inline av_const int av_popcount_c(uint32_t x)\n{\n    x -= (x >> 1) & 0x55555555;\n    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);\n    x = (x + (x >> 4)) & 0x0F0F0F0F;\n    x += x >> 8;\n    return (x + (x >> 16)) & 0x3F;\n}\n\n/**\n * Count number of bits set to one in x\n * @param x value to count bits of\n * @return the number of bits set to one in x\n */\nstatic av_always_inline av_const int av_popcount64_c(uint64_t x)\n{\n    return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32));\n}\n\nstatic av_always_inline av_const int av_parity_c(uint32_t v)\n{\n    return av_popcount(v) & 1;\n}\n\n/**\n * Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form.\n *\n * @param val      Output value, must be an lvalue of type uint32_t.\n * @param GET_BYTE Expression reading one byte from the input.\n *                 Evaluated up to 7 times (4 for the currently\n *                 assigned Unicode range).  With a memory buffer\n *                 input, this could be *ptr++, or if you want to make sure\n *                 that *ptr stops at the end of a NULL terminated string then\n *                 *ptr ? *ptr++ : 0\n * @param ERROR    Expression to be evaluated on invalid input,\n *                 typically a goto statement.\n *\n * @warning ERROR should not contain a loop control statement which\n * could interact with the internal while loop, and should force an\n * exit from the macro code (e.g. through a goto or a return) in order\n * to prevent undefined results.\n */\n#define GET_UTF8(val, GET_BYTE, ERROR)\\\n    val= (GET_BYTE);\\\n    {\\\n        uint32_t top = (val & 128) >> 1;\\\n        if ((val & 0xc0) == 0x80 || val >= 0xFE)\\\n            {ERROR}\\\n        while (val & top) {\\\n            unsigned int tmp = (GET_BYTE) - 128;\\\n            if(tmp>>6)\\\n                {ERROR}\\\n            val= (val<<6) + tmp;\\\n            top <<= 5;\\\n        }\\\n        val &= (top << 1) - 1;\\\n    }\n\n/**\n * Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form.\n *\n * @param val       Output value, must be an lvalue of type uint32_t.\n * @param GET_16BIT Expression returning two bytes of UTF-16 data converted\n *                  to native byte order.  Evaluated one or two times.\n * @param ERROR     Expression to be evaluated on invalid input,\n *                  typically a goto statement.\n */\n#define GET_UTF16(val, GET_16BIT, ERROR)\\\n    val = (GET_16BIT);\\\n    {\\\n        unsigned int hi = val - 0xD800;\\\n        if (hi < 0x800) {\\\n            val = (GET_16BIT) - 0xDC00;\\\n            if (val > 0x3FFU || hi > 0x3FFU)\\\n                {ERROR}\\\n            val += (hi<<10) + 0x10000;\\\n        }\\\n    }\\\n\n/**\n * @def PUT_UTF8(val, tmp, PUT_BYTE)\n * Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long).\n * @param val is an input-only argument and should be of type uint32_t. It holds\n * a UCS-4 encoded Unicode character that is to be converted to UTF-8. If\n * val is given as a function it is executed only once.\n * @param tmp is a temporary variable and should be of type uint8_t. It\n * represents an intermediate value during conversion that is to be\n * output by PUT_BYTE.\n * @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination.\n * It could be a function or a statement, and uses tmp as the input byte.\n * For example, PUT_BYTE could be \"*output++ = tmp;\" PUT_BYTE will be\n * executed up to 4 times for values in the valid UTF-8 range and up to\n * 7 times in the general case, depending on the length of the converted\n * Unicode character.\n */\n#define PUT_UTF8(val, tmp, PUT_BYTE)\\\n    {\\\n        int bytes, shift;\\\n        uint32_t in = val;\\\n        if (in < 0x80) {\\\n            tmp = in;\\\n            PUT_BYTE\\\n        } else {\\\n            bytes = (av_log2(in) + 4) / 5;\\\n            shift = (bytes - 1) * 6;\\\n            tmp = (256 - (256 >> bytes)) | (in >> shift);\\\n            PUT_BYTE\\\n            while (shift >= 6) {\\\n                shift -= 6;\\\n                tmp = 0x80 | ((in >> shift) & 0x3f);\\\n                PUT_BYTE\\\n            }\\\n        }\\\n    }\n\n/**\n * @def PUT_UTF16(val, tmp, PUT_16BIT)\n * Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes).\n * @param val is an input-only argument and should be of type uint32_t. It holds\n * a UCS-4 encoded Unicode character that is to be converted to UTF-16. If\n * val is given as a function it is executed only once.\n * @param tmp is a temporary variable and should be of type uint16_t. It\n * represents an intermediate value during conversion that is to be\n * output by PUT_16BIT.\n * @param PUT_16BIT writes the converted UTF-16 data to any proper destination\n * in desired endianness. It could be a function or a statement, and uses tmp\n * as the input byte.  For example, PUT_BYTE could be \"*output++ = tmp;\"\n * PUT_BYTE will be executed 1 or 2 times depending on input character.\n */\n#define PUT_UTF16(val, tmp, PUT_16BIT)\\\n    {\\\n        uint32_t in = val;\\\n        if (in < 0x10000) {\\\n            tmp = in;\\\n            PUT_16BIT\\\n        } else {\\\n            tmp = 0xD800 | ((in - 0x10000) >> 10);\\\n            PUT_16BIT\\\n            tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\\\n            PUT_16BIT\\\n        }\\\n    }\\\n\n\n\n#include \"mem.h\"\n\n#ifdef HAVE_AV_CONFIG_H\n#    include \"internal.h\"\n#endif /* HAVE_AV_CONFIG_H */\n\n#endif /* AVUTIL_COMMON_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/cpu.h",
    "content": "/*\n * Copyright (c) 2000, 2001, 2002 Fabrice Bellard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_CPU_H\n#define AVUTIL_CPU_H\n\n#include <stddef.h>\n\n#define AV_CPU_FLAG_FORCE    0x80000000 /* force usage of selected flags (OR) */\n\n    /* lower 16 bits - CPU features */\n#define AV_CPU_FLAG_MMX          0x0001 ///< standard MMX\n#define AV_CPU_FLAG_MMXEXT       0x0002 ///< SSE integer functions or AMD MMX ext\n#define AV_CPU_FLAG_MMX2         0x0002 ///< SSE integer functions or AMD MMX ext\n#define AV_CPU_FLAG_3DNOW        0x0004 ///< AMD 3DNOW\n#define AV_CPU_FLAG_SSE          0x0008 ///< SSE functions\n#define AV_CPU_FLAG_SSE2         0x0010 ///< PIV SSE2 functions\n#define AV_CPU_FLAG_SSE2SLOW 0x40000000 ///< SSE2 supported, but usually not faster\n                                        ///< than regular MMX/SSE (e.g. Core1)\n#define AV_CPU_FLAG_3DNOWEXT     0x0020 ///< AMD 3DNowExt\n#define AV_CPU_FLAG_SSE3         0x0040 ///< Prescott SSE3 functions\n#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster\n                                        ///< than regular MMX/SSE (e.g. Core1)\n#define AV_CPU_FLAG_SSSE3        0x0080 ///< Conroe SSSE3 functions\n#define AV_CPU_FLAG_SSSE3SLOW 0x4000000 ///< SSSE3 supported, but usually not faster\n#define AV_CPU_FLAG_ATOM     0x10000000 ///< Atom processor, some SSSE3 instructions are slower\n#define AV_CPU_FLAG_SSE4         0x0100 ///< Penryn SSE4.1 functions\n#define AV_CPU_FLAG_SSE42        0x0200 ///< Nehalem SSE4.2 functions\n#define AV_CPU_FLAG_AESNI       0x80000 ///< Advanced Encryption Standard functions\n#define AV_CPU_FLAG_AVX          0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used\n#define AV_CPU_FLAG_AVXSLOW   0x8000000 ///< AVX supported, but slow when using YMM registers (e.g. Bulldozer)\n#define AV_CPU_FLAG_XOP          0x0400 ///< Bulldozer XOP functions\n#define AV_CPU_FLAG_FMA4         0x0800 ///< Bulldozer FMA4 functions\n#define AV_CPU_FLAG_CMOV         0x1000 ///< supports cmov instruction\n#define AV_CPU_FLAG_AVX2         0x8000 ///< AVX2 functions: requires OS support even if YMM registers aren't used\n#define AV_CPU_FLAG_FMA3        0x10000 ///< Haswell FMA3 functions\n#define AV_CPU_FLAG_BMI1        0x20000 ///< Bit Manipulation Instruction Set 1\n#define AV_CPU_FLAG_BMI2        0x40000 ///< Bit Manipulation Instruction Set 2\n#define AV_CPU_FLAG_AVX512     0x100000 ///< AVX-512 functions: requires OS support even if YMM/ZMM registers aren't used\n#define AV_CPU_FLAG_AVX512ICL  0x200000 ///< F/CD/BW/DQ/VL/VNNI/IFMA/VBMI/VBMI2/VPOPCNTDQ/BITALG/GFNI/VAES/VPCLMULQDQ\n#define AV_CPU_FLAG_SLOW_GATHER  0x2000000 ///< CPU has slow gathers.\n\n#define AV_CPU_FLAG_ALTIVEC      0x0001 ///< standard\n#define AV_CPU_FLAG_VSX          0x0002 ///< ISA 2.06\n#define AV_CPU_FLAG_POWER8       0x0004 ///< ISA 2.07\n\n#define AV_CPU_FLAG_ARMV5TE      (1 << 0)\n#define AV_CPU_FLAG_ARMV6        (1 << 1)\n#define AV_CPU_FLAG_ARMV6T2      (1 << 2)\n#define AV_CPU_FLAG_VFP          (1 << 3)\n#define AV_CPU_FLAG_VFPV3        (1 << 4)\n#define AV_CPU_FLAG_NEON         (1 << 5)\n#define AV_CPU_FLAG_ARMV8        (1 << 6)\n#define AV_CPU_FLAG_VFP_VM       (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations\n#define AV_CPU_FLAG_SETEND       (1 <<16)\n\n#define AV_CPU_FLAG_MMI          (1 << 0)\n#define AV_CPU_FLAG_MSA          (1 << 1)\n\n//Loongarch SIMD extension.\n#define AV_CPU_FLAG_LSX          (1 << 0)\n#define AV_CPU_FLAG_LASX         (1 << 1)\n\n/**\n * Return the flags which specify extensions supported by the CPU.\n * The returned value is affected by av_force_cpu_flags() if that was used\n * before. So av_get_cpu_flags() can easily be used in an application to\n * detect the enabled cpu flags.\n */\nint av_get_cpu_flags(void);\n\n/**\n * Disables cpu detection and forces the specified flags.\n * -1 is a special case that disables forcing of specific flags.\n */\nvoid av_force_cpu_flags(int flags);\n\n/**\n * Parse CPU caps from a string and update the given AV_CPU_* flags based on that.\n *\n * @return negative on error.\n */\nint av_parse_cpu_caps(unsigned *flags, const char *s);\n\n/**\n * @return the number of logical CPU cores present.\n */\nint av_cpu_count(void);\n\n/**\n * Overrides cpu count detection and forces the specified count.\n * Count < 1 disables forcing of specific count.\n */\nvoid av_cpu_force_count(int count);\n\n/**\n * Get the maximum data alignment that may be required by FFmpeg.\n *\n * Note that this is affected by the build configuration and the CPU flags mask,\n * so e.g. if the CPU supports AVX, but libavutil has been built with\n * --disable-avx or the AV_CPU_FLAG_AVX flag has been disabled through\n *  av_set_cpu_flags_mask(), then this function will behave as if AVX is not\n *  present.\n */\nsize_t av_cpu_max_align(void);\n\n#endif /* AVUTIL_CPU_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/crc.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_crc32\n * Public header for CRC hash function implementation.\n */\n\n#ifndef AVUTIL_CRC_H\n#define AVUTIL_CRC_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"attributes.h\"\n\n/**\n * @defgroup lavu_crc32 CRC\n * @ingroup lavu_hash\n * CRC (Cyclic Redundancy Check) hash function implementation.\n *\n * This module supports numerous CRC polynomials, in addition to the most\n * widely used CRC-32-IEEE. See @ref AVCRCId for a list of available\n * polynomials.\n *\n * @{\n */\n\ntypedef uint32_t AVCRC;\n\ntypedef enum {\n    AV_CRC_8_ATM,\n    AV_CRC_16_ANSI,\n    AV_CRC_16_CCITT,\n    AV_CRC_32_IEEE,\n    AV_CRC_32_IEEE_LE,  /*< reversed bitorder version of AV_CRC_32_IEEE */\n    AV_CRC_16_ANSI_LE,  /*< reversed bitorder version of AV_CRC_16_ANSI */\n    AV_CRC_24_IEEE,\n    AV_CRC_8_EBU,\n    AV_CRC_MAX,         /*< Not part of public API! Do not use outside libavutil. */\n}AVCRCId;\n\n/**\n * Initialize a CRC table.\n * @param ctx must be an array of size sizeof(AVCRC)*257 or sizeof(AVCRC)*1024\n * @param le If 1, the lowest bit represents the coefficient for the highest\n *           exponent of the corresponding polynomial (both for poly and\n *           actual CRC).\n *           If 0, you must swap the CRC parameter and the result of av_crc\n *           if you need the standard representation (can be simplified in\n *           most cases to e.g. bswap16):\n *           av_bswap32(crc << (32-bits))\n * @param bits number of bits for the CRC\n * @param poly generator polynomial without the x**bits coefficient, in the\n *             representation as specified by le\n * @param ctx_size size of ctx in bytes\n * @return <0 on failure\n */\nint av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size);\n\n/**\n * Get an initialized standard CRC table.\n * @param crc_id ID of a standard CRC\n * @return a pointer to the CRC table or NULL on failure\n */\nconst AVCRC *av_crc_get_table(AVCRCId crc_id);\n\n/**\n * Calculate the CRC of a block.\n * @param crc CRC of previous blocks if any or initial value for CRC\n * @return CRC updated with the data from the given block\n *\n * @see av_crc_init() \"le\" parameter\n */\nuint32_t av_crc(const AVCRC *ctx, uint32_t crc,\n                const uint8_t *buffer, size_t length) av_pure;\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_CRC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/csp.h",
    "content": "/*\n * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com>\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_CSP_H\n#define AVUTIL_CSP_H\n\n#include \"pixfmt.h\"\n#include \"rational.h\"\n\n/**\n * @file Colorspace value utility functions for libavutil.\n * @author Ronald S. Bultje <rsbultje@gmail.com>\n * @author Leo Izen <leo.izen@gmail.com>\n * @defgroup lavu_math_csp Colorspace Utility\n * @ingroup lavu_math\n * @{\n */\n\n/**\n * Struct containing luma coefficients to be used for RGB to YUV/YCoCg, or similar\n * calculations.\n */\ntypedef struct AVLumaCoefficients {\n    AVRational cr, cg, cb;\n} AVLumaCoefficients;\n\n/**\n * Struct containing chromaticity x and y values for the standard CIE 1931\n * chromaticity definition.\n */\ntypedef struct AVCIExy {\n    AVRational x, y;\n} AVCIExy;\n\n/**\n * Struct defining the red, green, and blue primary locations in terms of CIE\n * 1931 chromaticity x and y.\n */\ntypedef struct AVPrimaryCoefficients {\n    AVCIExy r, g, b;\n} AVPrimaryCoefficients;\n\n/**\n * Struct defining white point location in terms of CIE 1931 chromaticity x\n * and y.\n */\ntypedef AVCIExy AVWhitepointCoefficients;\n\n/**\n * Struct that contains both white point location and primaries location, providing\n * the complete description of a color gamut.\n */\ntypedef struct AVColorPrimariesDesc {\n    AVWhitepointCoefficients wp;\n    AVPrimaryCoefficients prim;\n} AVColorPrimariesDesc;\n\n/**\n * Retrieves the Luma coefficients necessary to construct a conversion matrix\n * from an enum constant describing the colorspace.\n * @param csp An enum constant indicating YUV or similar colorspace.\n * @return The Luma coefficients associated with that colorspace, or NULL\n *     if the constant is unknown to libavutil.\n */\nconst AVLumaCoefficients *av_csp_luma_coeffs_from_avcsp(enum AVColorSpace csp);\n\n/**\n * Retrieves a complete gamut description from an enum constant describing the\n * color primaries.\n * @param prm An enum constant indicating primaries\n * @return A description of the colorspace gamut associated with that enum\n *     constant, or NULL if the constant is unknown to libavutil.\n */\nconst AVColorPrimariesDesc *av_csp_primaries_desc_from_id(enum AVColorPrimaries prm);\n\n/**\n * Detects which enum AVColorPrimaries constant corresponds to the given complete\n * gamut description.\n * @see enum AVColorPrimaries\n * @param prm A description of the colorspace gamut\n * @return The enum constant associated with this gamut, or\n *     AVCOL_PRI_UNSPECIFIED if no clear match can be idenitified.\n */\nenum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_CSP_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/des.h",
    "content": "/*\n * DES encryption/decryption\n * Copyright (c) 2007 Reimar Doeffinger\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_DES_H\n#define AVUTIL_DES_H\n\n#include <stdint.h>\n\n/**\n * @defgroup lavu_des DES\n * @ingroup lavu_crypto\n * @{\n */\n\ntypedef struct AVDES {\n    uint64_t round_keys[3][16];\n    int triple_des;\n} AVDES;\n\n/**\n * Allocate an AVDES context.\n */\nAVDES *av_des_alloc(void);\n\n/**\n * @brief Initializes an AVDES context.\n *\n * @param key_bits must be 64 or 192\n * @param decrypt 0 for encryption/CBC-MAC, 1 for decryption\n * @return zero on success, negative value otherwise\n */\nint av_des_init(struct AVDES *d, const uint8_t *key, int key_bits, int decrypt);\n\n/**\n * @brief Encrypts / decrypts using the DES algorithm.\n *\n * @param count number of 8 byte blocks\n * @param dst destination array, can be equal to src, must be 8-byte aligned\n * @param src source array, can be equal to dst, must be 8-byte aligned, may be NULL\n * @param iv initialization vector for CBC mode, if NULL then ECB will be used,\n *           must be 8-byte aligned\n * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_des_crypt(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);\n\n/**\n * @brief Calculates CBC-MAC using the DES algorithm.\n *\n * @param count number of 8 byte blocks\n * @param dst destination array, can be equal to src, must be 8-byte aligned\n * @param src source array, can be equal to dst, must be 8-byte aligned, may be NULL\n */\nvoid av_des_mac(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_DES_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/detection_bbox.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_DETECTION_BBOX_H\n#define AVUTIL_DETECTION_BBOX_H\n\n#include \"rational.h\"\n#include \"avassert.h\"\n#include \"frame.h\"\n\ntypedef struct AVDetectionBBox {\n    /**\n     * Distance in pixels from the left/top edge of the frame,\n     * together with width and height, defining the bounding box.\n     */\n    int x;\n    int y;\n    int w;\n    int h;\n\n#define AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE 64\n\n    /**\n     * Detect result with confidence\n     */\n    char detect_label[AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE];\n    AVRational detect_confidence;\n\n    /**\n     * At most 4 classifications based on the detected bounding box.\n     * For example, we can get max 4 different attributes with 4 different\n     * DNN models on one bounding box.\n     * classify_count is zero if no classification.\n     */\n#define AV_NUM_DETECTION_BBOX_CLASSIFY 4\n    uint32_t classify_count;\n    char classify_labels[AV_NUM_DETECTION_BBOX_CLASSIFY][AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE];\n    AVRational classify_confidences[AV_NUM_DETECTION_BBOX_CLASSIFY];\n} AVDetectionBBox;\n\ntypedef struct AVDetectionBBoxHeader {\n    /**\n     * Information about how the bounding box is generated.\n     * for example, the DNN model name.\n     */\n    char source[256];\n\n    /**\n     * Number of bounding boxes in the array.\n     */\n    uint32_t nb_bboxes;\n\n    /**\n     * Offset in bytes from the beginning of this structure at which\n     * the array of bounding boxes starts.\n     */\n    size_t bboxes_offset;\n\n    /**\n     * Size of each bounding box in bytes.\n     */\n    size_t bbox_size;\n} AVDetectionBBoxHeader;\n\n/*\n * Get the bounding box at the specified {@code idx}. Must be between 0 and nb_bboxes.\n */\nstatic av_always_inline AVDetectionBBox *\nav_get_detection_bbox(const AVDetectionBBoxHeader *header, unsigned int idx)\n{\n    av_assert0(idx < header->nb_bboxes);\n    return (AVDetectionBBox *)((uint8_t *)header + header->bboxes_offset +\n                               idx * header->bbox_size);\n}\n\n/**\n * Allocates memory for AVDetectionBBoxHeader, plus an array of {@code nb_bboxes}\n * AVDetectionBBox, and initializes the variables.\n * Can be freed with a normal av_free() call.\n *\n * @param out_size if non-NULL, the size in bytes of the resulting data array is\n * written here.\n */\nAVDetectionBBoxHeader *av_detection_bbox_alloc(uint32_t nb_bboxes, size_t *out_size);\n\n/**\n * Allocates memory for AVDetectionBBoxHeader, plus an array of {@code nb_bboxes}\n * AVDetectionBBox, in the given AVFrame {@code frame} as AVFrameSideData of type\n * AV_FRAME_DATA_DETECTION_BBOXES and initializes the variables.\n */\nAVDetectionBBoxHeader *av_detection_bbox_create_side_data(AVFrame *frame, uint32_t nb_bboxes);\n#endif\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/dict.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * Public dictionary API.\n * @deprecated\n *  AVDictionary is provided for compatibility with libav. It is both in\n *  implementation as well as API inefficient. It does not scale and is\n *  extremely slow with large dictionaries.\n *  It is recommended that new code uses our tree container from tree.c/h\n *  where applicable, which uses AVL trees to achieve O(log n) performance.\n */\n\n#ifndef AVUTIL_DICT_H\n#define AVUTIL_DICT_H\n\n#include <stdint.h>\n\n/**\n * @addtogroup lavu_dict AVDictionary\n * @ingroup lavu_data\n *\n * @brief Simple key:value store\n *\n * @{\n * Dictionaries are used for storing key:value pairs. To create\n * an AVDictionary, simply pass an address of a NULL pointer to\n * av_dict_set(). NULL can be used as an empty dictionary wherever\n * a pointer to an AVDictionary is required.\n * Use av_dict_get() to retrieve an entry or iterate over all\n * entries and finally av_dict_free() to free the dictionary\n * and all its contents.\n *\n @code\n   AVDictionary *d = NULL;           // \"create\" an empty dictionary\n   AVDictionaryEntry *t = NULL;\n\n   av_dict_set(&d, \"foo\", \"bar\", 0); // add an entry\n\n   char *k = av_strdup(\"key\");       // if your strings are already allocated,\n   char *v = av_strdup(\"value\");     // you can avoid copying them like this\n   av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);\n\n   while (t = av_dict_get(d, \"\", t, AV_DICT_IGNORE_SUFFIX)) {\n       <....>                             // iterate over all entries in d\n   }\n   av_dict_free(&d);\n @endcode\n */\n\n#define AV_DICT_MATCH_CASE      1   /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */\n#define AV_DICT_IGNORE_SUFFIX   2   /**< Return first entry in a dictionary whose first part corresponds to the search key,\n                                         ignoring the suffix of the found key string. Only relevant in av_dict_get(). */\n#define AV_DICT_DONT_STRDUP_KEY 4   /**< Take ownership of a key that's been\n                                         allocated with av_malloc() or another memory allocation function. */\n#define AV_DICT_DONT_STRDUP_VAL 8   /**< Take ownership of a value that's been\n                                         allocated with av_malloc() or another memory allocation function. */\n#define AV_DICT_DONT_OVERWRITE 16   ///< Don't overwrite existing entries.\n#define AV_DICT_APPEND         32   /**< If the entry already exists, append to it.  Note that no\n                                      delimiter is added, the strings are simply concatenated. */\n#define AV_DICT_MULTIKEY       64   /**< Allow to store several equal keys in the dictionary */\n\ntypedef struct AVDictionaryEntry {\n    char *key;\n    char *value;\n} AVDictionaryEntry;\n\ntypedef struct AVDictionary AVDictionary;\n\n/**\n * Get a dictionary entry with matching key.\n *\n * The returned entry key or value must not be changed, or it will\n * cause undefined behavior.\n *\n * To iterate through all the dictionary entries, you can set the matching key\n * to the null string \"\" and set the AV_DICT_IGNORE_SUFFIX flag.\n *\n * @param prev Set to the previous matching element to find the next.\n *             If set to NULL the first matching element is returned.\n * @param key matching key\n * @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved\n * @return found entry or NULL in case no matching entry was found in the dictionary\n */\nAVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,\n                               const AVDictionaryEntry *prev, int flags);\n\n/**\n * Get number of entries in dictionary.\n *\n * @param m dictionary\n * @return  number of entries in dictionary\n */\nint av_dict_count(const AVDictionary *m);\n\n/**\n * Set the given entry in *pm, overwriting an existing entry.\n *\n * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set,\n * these arguments will be freed on error.\n *\n * Warning: Adding a new entry to a dictionary invalidates all existing entries\n * previously returned with av_dict_get.\n *\n * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL\n * a dictionary struct is allocated and put in *pm.\n * @param key entry key to add to *pm (will either be av_strduped or added as a new key depending on flags)\n * @param value entry value to add to *pm (will be av_strduped or added as a new key depending on flags).\n *        Passing a NULL value will cause an existing entry to be deleted.\n * @return >= 0 on success otherwise an error code <0\n */\nint av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags);\n\n/**\n * Convenience wrapper for av_dict_set that converts the value to a string\n * and stores it.\n *\n * Note: If AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error.\n */\nint av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags);\n\n/**\n * Parse the key/value pairs list and add the parsed entries to a dictionary.\n *\n * In case of failure, all the successfully set entries are stored in\n * *pm. You may need to manually free the created dictionary.\n *\n * @param key_val_sep  a 0-terminated list of characters used to separate\n *                     key from value\n * @param pairs_sep    a 0-terminated list of characters used to separate\n *                     two pairs from each other\n * @param flags        flags to use when adding to dictionary.\n *                     AV_DICT_DONT_STRDUP_KEY and AV_DICT_DONT_STRDUP_VAL\n *                     are ignored since the key/value tokens will always\n *                     be duplicated.\n * @return             0 on success, negative AVERROR code on failure\n */\nint av_dict_parse_string(AVDictionary **pm, const char *str,\n                         const char *key_val_sep, const char *pairs_sep,\n                         int flags);\n\n/**\n * Copy entries from one AVDictionary struct into another.\n * @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL,\n *            this function will allocate a struct for you and put it in *dst\n * @param src pointer to source AVDictionary struct\n * @param flags flags to use when setting entries in *dst\n * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag\n * @return 0 on success, negative AVERROR code on failure. If dst was allocated\n *           by this function, callers should free the associated memory.\n */\nint av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags);\n\n/**\n * Free all the memory allocated for an AVDictionary struct\n * and all keys and values.\n */\nvoid av_dict_free(AVDictionary **m);\n\n/**\n * Get dictionary entries as a string.\n *\n * Create a string containing dictionary's entries.\n * Such string may be passed back to av_dict_parse_string().\n * @note String is escaped with backslashes ('\\').\n *\n * @param[in]  m             dictionary\n * @param[out] buffer        Pointer to buffer that will be allocated with string containg entries.\n *                           Buffer must be freed by the caller when is no longer needed.\n * @param[in]  key_val_sep   character used to separate key from value\n * @param[in]  pairs_sep     character used to separate two pairs from each other\n * @return                   >= 0 on success, negative on error\n * @warning Separators cannot be neither '\\\\' nor '\\0'. They also cannot be the same.\n */\nint av_dict_get_string(const AVDictionary *m, char **buffer,\n                       const char key_val_sep, const char pairs_sep);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_DICT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/display.h",
    "content": "/*\n * Copyright (c) 2014 Vittorio Giovara <vittorio.giovara@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * Display matrix\n */\n\n#ifndef AVUTIL_DISPLAY_H\n#define AVUTIL_DISPLAY_H\n\n#include <stdint.h>\n\n/**\n * @addtogroup lavu_video\n * @{\n *\n * @defgroup lavu_video_display Display transformation matrix functions\n * @{\n */\n\n/**\n * @addtogroup lavu_video_display\n * The display transformation matrix specifies an affine transformation that\n * should be applied to video frames for correct presentation. It is compatible\n * with the matrices stored in the ISO/IEC 14496-12 container format.\n *\n * The data is a 3x3 matrix represented as a 9-element array:\n *\n * @code{.unparsed}\n *                                  | a b u |\n *   (a, b, u, c, d, v, x, y, w) -> | c d v |\n *                                  | x y w |\n * @endcode\n *\n * All numbers are stored in native endianness, as 16.16 fixed-point values,\n * except for u, v and w, which are stored as 2.30 fixed-point values.\n *\n * The transformation maps a point (p, q) in the source (pre-transformation)\n * frame to the point (p', q') in the destination (post-transformation) frame as\n * follows:\n *\n * @code{.unparsed}\n *               | a b u |\n *   (p, q, 1) . | c d v | = z * (p', q', 1)\n *               | x y w |\n * @endcode\n *\n * The transformation can also be more explicitly written in components as\n * follows:\n *\n * @code{.unparsed}\n *   p' = (a * p + c * q + x) / z;\n *   q' = (b * p + d * q + y) / z;\n *   z  =  u * p + v * q + w\n * @endcode\n */\n\n/**\n * Extract the rotation component of the transformation matrix.\n *\n * @param matrix the transformation matrix\n * @return the angle (in degrees) by which the transformation rotates the frame\n *         counterclockwise. The angle will be in range [-180.0, 180.0],\n *         or NaN if the matrix is singular.\n *\n * @note floating point numbers are inherently inexact, so callers are\n *       recommended to round the return value to nearest integer before use.\n */\ndouble av_display_rotation_get(const int32_t matrix[9]);\n\n/**\n * Initialize a transformation matrix describing a pure clockwise\n * rotation by the specified angle (in degrees).\n *\n * @param matrix an allocated transformation matrix (will be fully overwritten\n *               by this function)\n * @param angle rotation angle in degrees.\n */\nvoid av_display_rotation_set(int32_t matrix[9], double angle);\n\n/**\n * Flip the input matrix horizontally and/or vertically.\n *\n * @param matrix an allocated transformation matrix\n * @param hflip whether the matrix should be flipped horizontally\n * @param vflip whether the matrix should be flipped vertically\n */\nvoid av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip);\n\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_DISPLAY_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/dovi_meta.h",
    "content": "/*\n * Copyright (c) 2020 Vacing Fang <vacingfang@tencent.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * DOVI configuration\n */\n\n\n#ifndef AVUTIL_DOVI_META_H\n#define AVUTIL_DOVI_META_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"rational.h\"\n\n/*\n * DOVI configuration\n * ref: dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2\n        dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2\n * @code\n * uint8_t  dv_version_major, the major version number that the stream complies with\n * uint8_t  dv_version_minor, the minor version number that the stream complies with\n * uint8_t  dv_profile, the Dolby Vision profile\n * uint8_t  dv_level, the Dolby Vision level\n * uint8_t  rpu_present_flag\n * uint8_t  el_present_flag\n * uint8_t  bl_present_flag\n * uint8_t  dv_bl_signal_compatibility_id\n * @endcode\n *\n * @note The struct must be allocated with av_dovi_alloc() and\n *       its size is not a part of the public ABI.\n */\ntypedef struct AVDOVIDecoderConfigurationRecord {\n    uint8_t dv_version_major;\n    uint8_t dv_version_minor;\n    uint8_t dv_profile;\n    uint8_t dv_level;\n    uint8_t rpu_present_flag;\n    uint8_t el_present_flag;\n    uint8_t bl_present_flag;\n    uint8_t dv_bl_signal_compatibility_id;\n} AVDOVIDecoderConfigurationRecord;\n\n/**\n * Allocate a AVDOVIDecoderConfigurationRecord structure and initialize its\n * fields to default values.\n *\n * @return the newly allocated struct or NULL on failure\n */\nAVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size);\n\n/**\n * Dolby Vision RPU data header.\n *\n * @note sizeof(AVDOVIRpuDataHeader) is not part of the public ABI.\n */\ntypedef struct AVDOVIRpuDataHeader {\n    uint8_t rpu_type;\n    uint16_t rpu_format;\n    uint8_t vdr_rpu_profile;\n    uint8_t vdr_rpu_level;\n    uint8_t chroma_resampling_explicit_filter_flag;\n    uint8_t coef_data_type; /* informative, lavc always converts to fixed */\n    uint8_t coef_log2_denom;\n    uint8_t vdr_rpu_normalized_idc;\n    uint8_t bl_video_full_range_flag;\n    uint8_t bl_bit_depth; /* [8, 16] */\n    uint8_t el_bit_depth; /* [8, 16] */\n    uint8_t vdr_bit_depth; /* [8, 16] */\n    uint8_t spatial_resampling_filter_flag;\n    uint8_t el_spatial_resampling_filter_flag;\n    uint8_t disable_residual_flag;\n} AVDOVIRpuDataHeader;\n\nenum AVDOVIMappingMethod {\n    AV_DOVI_MAPPING_POLYNOMIAL = 0,\n    AV_DOVI_MAPPING_MMR = 1,\n};\n\n/**\n * Coefficients of a piece-wise function. The pieces of the function span the\n * value ranges between two adjacent pivot values.\n */\n#define AV_DOVI_MAX_PIECES 8\ntypedef struct AVDOVIReshapingCurve {\n    uint8_t num_pivots;                         /* [2, 9] */\n    uint16_t pivots[AV_DOVI_MAX_PIECES + 1];    /* sorted ascending */\n    enum AVDOVIMappingMethod mapping_idc[AV_DOVI_MAX_PIECES];\n    /* AV_DOVI_MAPPING_POLYNOMIAL */\n    uint8_t poly_order[AV_DOVI_MAX_PIECES];     /* [1, 2] */\n    int64_t poly_coef[AV_DOVI_MAX_PIECES][3];   /* x^0, x^1, x^2 */\n    /* AV_DOVI_MAPPING_MMR */\n    uint8_t mmr_order[AV_DOVI_MAX_PIECES];      /* [1, 3] */\n    int64_t mmr_constant[AV_DOVI_MAX_PIECES];\n    int64_t mmr_coef[AV_DOVI_MAX_PIECES][3/* order - 1 */][7];\n} AVDOVIReshapingCurve;\n\nenum AVDOVINLQMethod {\n    AV_DOVI_NLQ_NONE = -1,\n    AV_DOVI_NLQ_LINEAR_DZ = 0,\n};\n\n/**\n * Coefficients of the non-linear inverse quantization. For the interpretation\n * of these, see ETSI GS CCM 001.\n */\ntypedef struct AVDOVINLQParams {\n    uint16_t nlq_offset;\n    uint64_t vdr_in_max;\n    /* AV_DOVI_NLQ_LINEAR_DZ */\n    uint64_t linear_deadzone_slope;\n    uint64_t linear_deadzone_threshold;\n} AVDOVINLQParams;\n\n/**\n * Dolby Vision RPU data mapping parameters.\n *\n * @note sizeof(AVDOVIDataMapping) is not part of the public ABI.\n */\ntypedef struct AVDOVIDataMapping {\n    uint8_t vdr_rpu_id;\n    uint8_t mapping_color_space;\n    uint8_t mapping_chroma_format_idc;\n    AVDOVIReshapingCurve curves[3]; /* per component */\n\n    /* Non-linear inverse quantization */\n    enum AVDOVINLQMethod nlq_method_idc;\n    uint32_t num_x_partitions;\n    uint32_t num_y_partitions;\n    AVDOVINLQParams nlq[3]; /* per component */\n} AVDOVIDataMapping;\n\n/**\n * Dolby Vision RPU colorspace metadata parameters.\n *\n * @note sizeof(AVDOVIColorMetadata) is not part of the public ABI.\n */\ntypedef struct AVDOVIColorMetadata {\n    uint8_t dm_metadata_id;\n    uint8_t scene_refresh_flag;\n\n    /**\n     * Coefficients of the custom Dolby Vision IPT-PQ matrices. These are to be\n     * used instead of the matrices indicated by the frame's colorspace tags.\n     * The output of rgb_to_lms_matrix is to be fed into a BT.2020 LMS->RGB\n     * matrix based on a Hunt-Pointer-Estevez transform, but without any\n     * crosstalk. (See the definition of the ICtCp colorspace for more\n     * information.)\n     */\n    AVRational ycc_to_rgb_matrix[9]; /* before PQ linearization */\n    AVRational ycc_to_rgb_offset[3]; /* input offset of neutral value */\n    AVRational rgb_to_lms_matrix[9]; /* after PQ linearization */\n\n    /**\n     * Extra signal metadata (see Dolby patents for more info).\n     */\n    uint16_t signal_eotf;\n    uint16_t signal_eotf_param0;\n    uint16_t signal_eotf_param1;\n    uint32_t signal_eotf_param2;\n    uint8_t signal_bit_depth;\n    uint8_t signal_color_space;\n    uint8_t signal_chroma_format;\n    uint8_t signal_full_range_flag; /* [0, 3] */\n    uint16_t source_min_pq;\n    uint16_t source_max_pq;\n    uint16_t source_diagonal;\n} AVDOVIColorMetadata;\n\n/**\n * Combined struct representing a combination of header, mapping and color\n * metadata, for attaching to frames as side data.\n *\n * @note The struct must be allocated with av_dovi_metadata_alloc() and\n *       its size is not a part of the public ABI.\n */\n\ntypedef struct AVDOVIMetadata {\n    /**\n     * Offset in bytes from the beginning of this structure at which the\n     * respective structs start.\n     */\n    size_t header_offset;   /* AVDOVIRpuDataHeader */\n    size_t mapping_offset;  /* AVDOVIDataMapping */\n    size_t color_offset;    /* AVDOVIColorMetadata */\n} AVDOVIMetadata;\n\nstatic av_always_inline AVDOVIRpuDataHeader *\nav_dovi_get_header(const AVDOVIMetadata *data)\n{\n    return (AVDOVIRpuDataHeader *)((uint8_t *) data + data->header_offset);\n}\n\nstatic av_always_inline AVDOVIDataMapping *\nav_dovi_get_mapping(const AVDOVIMetadata *data)\n{\n    return (AVDOVIDataMapping *)((uint8_t *) data + data->mapping_offset);\n}\n\nstatic av_always_inline AVDOVIColorMetadata *\nav_dovi_get_color(const AVDOVIMetadata *data)\n{\n    return (AVDOVIColorMetadata *)((uint8_t *) data + data->color_offset);\n}\n\n/**\n * Allocate an AVDOVIMetadata structure and initialize its\n * fields to default values.\n *\n * @param size If this parameter is non-NULL, the size in bytes of the\n *             allocated struct will be written here on success\n *\n * @return the newly allocated struct or NULL on failure\n */\nAVDOVIMetadata *av_dovi_metadata_alloc(size_t *size);\n\n#endif /* AVUTIL_DOVI_META_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/downmix_info.h",
    "content": "/*\n * Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_DOWNMIX_INFO_H\n#define AVUTIL_DOWNMIX_INFO_H\n\n#include \"frame.h\"\n\n/**\n * @file\n * audio downmix medatata\n */\n\n/**\n * @addtogroup lavu_audio\n * @{\n */\n\n/**\n * @defgroup downmix_info Audio downmix metadata\n * @{\n */\n\n/**\n * Possible downmix types.\n */\nenum AVDownmixType {\n    AV_DOWNMIX_TYPE_UNKNOWN, /**< Not indicated. */\n    AV_DOWNMIX_TYPE_LORO,    /**< Lo/Ro 2-channel downmix (Stereo). */\n    AV_DOWNMIX_TYPE_LTRT,    /**< Lt/Rt 2-channel downmix, Dolby Surround compatible. */\n    AV_DOWNMIX_TYPE_DPLII,   /**< Lt/Rt 2-channel downmix, Dolby Pro Logic II compatible. */\n    AV_DOWNMIX_TYPE_NB       /**< Number of downmix types. Not part of ABI. */\n};\n\n/**\n * This structure describes optional metadata relevant to a downmix procedure.\n *\n * All fields are set by the decoder to the value indicated in the audio\n * bitstream (if present), or to a \"sane\" default otherwise.\n */\ntypedef struct AVDownmixInfo {\n    /**\n     * Type of downmix preferred by the mastering engineer.\n     */\n    enum AVDownmixType preferred_downmix_type;\n\n    /**\n     * Absolute scale factor representing the nominal level of the center\n     * channel during a regular downmix.\n     */\n    double center_mix_level;\n\n    /**\n     * Absolute scale factor representing the nominal level of the center\n     * channel during an Lt/Rt compatible downmix.\n     */\n    double center_mix_level_ltrt;\n\n    /**\n     * Absolute scale factor representing the nominal level of the surround\n     * channels during a regular downmix.\n     */\n    double surround_mix_level;\n\n    /**\n     * Absolute scale factor representing the nominal level of the surround\n     * channels during an Lt/Rt compatible downmix.\n     */\n    double surround_mix_level_ltrt;\n\n    /**\n     * Absolute scale factor representing the level at which the LFE data is\n     * mixed into L/R channels during downmixing.\n     */\n    double lfe_mix_level;\n} AVDownmixInfo;\n\n/**\n * Get a frame's AV_FRAME_DATA_DOWNMIX_INFO side data for editing.\n *\n * If the side data is absent, it is created and added to the frame.\n *\n * @param frame the frame for which the side data is to be obtained or created\n *\n * @return the AVDownmixInfo structure to be edited by the caller, or NULL if\n *         the structure cannot be allocated.\n */\nAVDownmixInfo *av_downmix_info_update_side_data(AVFrame *frame);\n\n/**\n * @}\n */\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_DOWNMIX_INFO_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/encryption_info.h",
    "content": "/**\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_ENCRYPTION_INFO_H\n#define AVUTIL_ENCRYPTION_INFO_H\n\n#include <stddef.h>\n#include <stdint.h>\n\ntypedef struct AVSubsampleEncryptionInfo {\n    /** The number of bytes that are clear. */\n    unsigned int bytes_of_clear_data;\n\n    /**\n     * The number of bytes that are protected.  If using pattern encryption,\n     * the pattern applies to only the protected bytes; if not using pattern\n     * encryption, all these bytes are encrypted.\n     */\n    unsigned int bytes_of_protected_data;\n} AVSubsampleEncryptionInfo;\n\n/**\n * This describes encryption info for a packet.  This contains frame-specific\n * info for how to decrypt the packet before passing it to the decoder.\n *\n * The size of this struct is not part of the public ABI.\n */\ntypedef struct AVEncryptionInfo {\n    /** The fourcc encryption scheme, in big-endian byte order. */\n    uint32_t scheme;\n\n    /**\n     * Only used for pattern encryption.  This is the number of 16-byte blocks\n     * that are encrypted.\n     */\n    uint32_t crypt_byte_block;\n\n    /**\n     * Only used for pattern encryption.  This is the number of 16-byte blocks\n     * that are clear.\n     */\n    uint32_t skip_byte_block;\n\n    /**\n     * The ID of the key used to encrypt the packet.  This should always be\n     * 16 bytes long, but may be changed in the future.\n     */\n    uint8_t *key_id;\n    uint32_t key_id_size;\n\n    /**\n     * The initialization vector.  This may have been zero-filled to be the\n     * correct block size.  This should always be 16 bytes long, but may be\n     * changed in the future.\n     */\n    uint8_t *iv;\n    uint32_t iv_size;\n\n    /**\n     * An array of subsample encryption info specifying how parts of the sample\n     * are encrypted.  If there are no subsamples, then the whole sample is\n     * encrypted.\n     */\n    AVSubsampleEncryptionInfo *subsamples;\n    uint32_t subsample_count;\n} AVEncryptionInfo;\n\n/**\n * This describes info used to initialize an encryption key system.\n *\n * The size of this struct is not part of the public ABI.\n */\ntypedef struct AVEncryptionInitInfo {\n    /**\n     * A unique identifier for the key system this is for, can be NULL if it\n     * is not known.  This should always be 16 bytes, but may change in the\n     * future.\n     */\n    uint8_t* system_id;\n    uint32_t system_id_size;\n\n    /**\n     * An array of key IDs this initialization data is for.  All IDs are the\n     * same length.  Can be NULL if there are no known key IDs.\n     */\n    uint8_t** key_ids;\n    /** The number of key IDs. */\n    uint32_t num_key_ids;\n    /**\n     * The number of bytes in each key ID.  This should always be 16, but may\n     * change in the future.\n     */\n    uint32_t key_id_size;\n\n    /**\n     * Key-system specific initialization data.  This data is copied directly\n     * from the file and the format depends on the specific key system.  This\n     * can be NULL if there is no initialization data; in that case, there\n     * will be at least one key ID.\n     */\n    uint8_t* data;\n    uint32_t data_size;\n\n    /**\n     * An optional pointer to the next initialization info in the list.\n     */\n    struct AVEncryptionInitInfo *next;\n} AVEncryptionInitInfo;\n\n/**\n * Allocates an AVEncryptionInfo structure and sub-pointers to hold the given\n * number of subsamples.  This will allocate pointers for the key ID, IV,\n * and subsample entries, set the size members, and zero-initialize the rest.\n *\n * @param subsample_count The number of subsamples.\n * @param key_id_size The number of bytes in the key ID, should be 16.\n * @param iv_size The number of bytes in the IV, should be 16.\n *\n * @return The new AVEncryptionInfo structure, or NULL on error.\n */\nAVEncryptionInfo *av_encryption_info_alloc(uint32_t subsample_count, uint32_t key_id_size, uint32_t iv_size);\n\n/**\n * Allocates an AVEncryptionInfo structure with a copy of the given data.\n * @return The new AVEncryptionInfo structure, or NULL on error.\n */\nAVEncryptionInfo *av_encryption_info_clone(const AVEncryptionInfo *info);\n\n/**\n * Frees the given encryption info object.  This MUST NOT be used to free the\n * side-data data pointer, that should use normal side-data methods.\n */\nvoid av_encryption_info_free(AVEncryptionInfo *info);\n\n/**\n * Creates a copy of the AVEncryptionInfo that is contained in the given side\n * data.  The resulting object should be passed to av_encryption_info_free()\n * when done.\n *\n * @return The new AVEncryptionInfo structure, or NULL on error.\n */\nAVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t *side_data, size_t side_data_size);\n\n/**\n * Allocates and initializes side data that holds a copy of the given encryption\n * info.  The resulting pointer should be either freed using av_free or given\n * to av_packet_add_side_data().\n *\n * @return The new side-data pointer, or NULL.\n */\nuint8_t *av_encryption_info_add_side_data(\n      const AVEncryptionInfo *info, size_t *side_data_size);\n\n\n/**\n * Allocates an AVEncryptionInitInfo structure and sub-pointers to hold the\n * given sizes.  This will allocate pointers and set all the fields.\n *\n * @return The new AVEncryptionInitInfo structure, or NULL on error.\n */\nAVEncryptionInitInfo *av_encryption_init_info_alloc(\n    uint32_t system_id_size, uint32_t num_key_ids, uint32_t key_id_size, uint32_t data_size);\n\n/**\n * Frees the given encryption init info object.  This MUST NOT be used to free\n * the side-data data pointer, that should use normal side-data methods.\n */\nvoid av_encryption_init_info_free(AVEncryptionInitInfo* info);\n\n/**\n * Creates a copy of the AVEncryptionInitInfo that is contained in the given\n * side data.  The resulting object should be passed to\n * av_encryption_init_info_free() when done.\n *\n * @return The new AVEncryptionInitInfo structure, or NULL on error.\n */\nAVEncryptionInitInfo *av_encryption_init_info_get_side_data(\n    const uint8_t* side_data, size_t side_data_size);\n\n/**\n * Allocates and initializes side data that holds a copy of the given encryption\n * init info.  The resulting pointer should be either freed using av_free or\n * given to av_packet_add_side_data().\n *\n * @return The new side-data pointer, or NULL.\n */\nuint8_t *av_encryption_init_info_add_side_data(\n    const AVEncryptionInitInfo *info, size_t *side_data_size);\n\n#endif /* AVUTIL_ENCRYPTION_INFO_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/error.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * error code definitions\n */\n\n#ifndef AVUTIL_ERROR_H\n#define AVUTIL_ERROR_H\n\n#include <errno.h>\n#include <stddef.h>\n\n#include \"macros.h\"\n\n/**\n * @addtogroup lavu_error\n *\n * @{\n */\n\n\n/* error handling */\n#if EDOM > 0\n#define AVERROR(e) (-(e))   ///< Returns a negative error code from a POSIX error code, to return from library functions.\n#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value.\n#else\n/* Some platforms have E* and errno already negated. */\n#define AVERROR(e) (e)\n#define AVUNERROR(e) (e)\n#endif\n\n#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d))\n\n#define AVERROR_BSF_NOT_FOUND      FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found\n#define AVERROR_BUG                FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2\n#define AVERROR_BUFFER_TOO_SMALL   FFERRTAG( 'B','U','F','S') ///< Buffer too small\n#define AVERROR_DECODER_NOT_FOUND  FFERRTAG(0xF8,'D','E','C') ///< Decoder not found\n#define AVERROR_DEMUXER_NOT_FOUND  FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found\n#define AVERROR_ENCODER_NOT_FOUND  FFERRTAG(0xF8,'E','N','C') ///< Encoder not found\n#define AVERROR_EOF                FFERRTAG( 'E','O','F',' ') ///< End of file\n#define AVERROR_EXIT               FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted\n#define AVERROR_EXTERNAL           FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library\n#define AVERROR_FILTER_NOT_FOUND   FFERRTAG(0xF8,'F','I','L') ///< Filter not found\n#define AVERROR_INVALIDDATA        FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input\n#define AVERROR_MUXER_NOT_FOUND    FFERRTAG(0xF8,'M','U','X') ///< Muxer not found\n#define AVERROR_OPTION_NOT_FOUND   FFERRTAG(0xF8,'O','P','T') ///< Option not found\n#define AVERROR_PATCHWELCOME       FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome\n#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found\n\n#define AVERROR_STREAM_NOT_FOUND   FFERRTAG(0xF8,'S','T','R') ///< Stream not found\n/**\n * This is semantically identical to AVERROR_BUG\n * it has been introduced in Libav after our AVERROR_BUG and with a modified value.\n */\n#define AVERROR_BUG2               FFERRTAG( 'B','U','G',' ')\n#define AVERROR_UNKNOWN            FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library\n#define AVERROR_EXPERIMENTAL       (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.\n#define AVERROR_INPUT_CHANGED      (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED)\n#define AVERROR_OUTPUT_CHANGED     (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)\n/* HTTP & RTSP errors */\n#define AVERROR_HTTP_BAD_REQUEST   FFERRTAG(0xF8,'4','0','0')\n#define AVERROR_HTTP_UNAUTHORIZED  FFERRTAG(0xF8,'4','0','1')\n#define AVERROR_HTTP_FORBIDDEN     FFERRTAG(0xF8,'4','0','3')\n#define AVERROR_HTTP_NOT_FOUND     FFERRTAG(0xF8,'4','0','4')\n#define AVERROR_HTTP_OTHER_4XX     FFERRTAG(0xF8,'4','X','X')\n#define AVERROR_HTTP_SERVER_ERROR  FFERRTAG(0xF8,'5','X','X')\n\n#define AV_ERROR_MAX_STRING_SIZE 64\n\n/**\n * Put a description of the AVERROR code errnum in errbuf.\n * In case of failure the global variable errno is set to indicate the\n * error. Even in case of failure av_strerror() will print a generic\n * error message indicating the errnum provided to errbuf.\n *\n * @param errnum      error code to describe\n * @param errbuf      buffer to which description is written\n * @param errbuf_size the size in bytes of errbuf\n * @return 0 on success, a negative value if a description for errnum\n * cannot be found\n */\nint av_strerror(int errnum, char *errbuf, size_t errbuf_size);\n\n/**\n * Fill the provided buffer with a string containing an error string\n * corresponding to the AVERROR code errnum.\n *\n * @param errbuf         a buffer\n * @param errbuf_size    size in bytes of errbuf\n * @param errnum         error code to describe\n * @return the buffer in input, filled with the error description\n * @see av_strerror()\n */\nstatic inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum)\n{\n    av_strerror(errnum, errbuf, errbuf_size);\n    return errbuf;\n}\n\n/**\n * Convenience macro, the return value should be used only directly in\n * function arguments but never stand-alone.\n */\n#define av_err2str(errnum) \\\n    av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum)\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_ERROR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/eval.h",
    "content": "/*\n * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * simple arithmetic expression evaluator\n */\n\n#ifndef AVUTIL_EVAL_H\n#define AVUTIL_EVAL_H\n\ntypedef struct AVExpr AVExpr;\n\n/**\n * Parse and evaluate an expression.\n * Note, this is significantly slower than av_expr_eval().\n *\n * @param res a pointer to a double where is put the result value of\n * the expression, or NAN in case of error\n * @param s expression as a zero terminated string, for example \"1+2^3+5*5+sin(2/3)\"\n * @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {\"PI\", \"E\", 0}\n * @param const_values a zero terminated array of values for the identifiers from const_names\n * @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers\n * @param funcs1 NULL terminated array of function pointers for functions which take 1 argument\n * @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers\n * @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments\n * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2\n * @param log_ctx parent logging context\n * @return >= 0 in case of success, a negative value corresponding to an\n * AVERROR code otherwise\n */\nint av_expr_parse_and_eval(double *res, const char *s,\n                           const char * const *const_names, const double *const_values,\n                           const char * const *func1_names, double (* const *funcs1)(void *, double),\n                           const char * const *func2_names, double (* const *funcs2)(void *, double, double),\n                           void *opaque, int log_offset, void *log_ctx);\n\n/**\n * Parse an expression.\n *\n * @param expr a pointer where is put an AVExpr containing the parsed\n * value in case of successful parsing, or NULL otherwise.\n * The pointed to AVExpr must be freed with av_expr_free() by the user\n * when it is not needed anymore.\n * @param s expression as a zero terminated string, for example \"1+2^3+5*5+sin(2/3)\"\n * @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {\"PI\", \"E\", 0}\n * @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers\n * @param funcs1 NULL terminated array of function pointers for functions which take 1 argument\n * @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers\n * @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments\n * @param log_ctx parent logging context\n * @return >= 0 in case of success, a negative value corresponding to an\n * AVERROR code otherwise\n */\nint av_expr_parse(AVExpr **expr, const char *s,\n                  const char * const *const_names,\n                  const char * const *func1_names, double (* const *funcs1)(void *, double),\n                  const char * const *func2_names, double (* const *funcs2)(void *, double, double),\n                  int log_offset, void *log_ctx);\n\n/**\n * Evaluate a previously parsed expression.\n *\n * @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names\n * @param opaque a pointer which will be passed to all functions from funcs1 and funcs2\n * @return the value of the expression\n */\ndouble av_expr_eval(AVExpr *e, const double *const_values, void *opaque);\n\n/**\n * Track the presence of variables and their number of occurrences in a parsed expression\n *\n * @param counter a zero-initialized array where the count of each variable will be stored\n * @param size size of array\n * @return 0 on success, a negative value indicates that no expression or array was passed\n * or size was zero\n */\nint av_expr_count_vars(AVExpr *e, unsigned *counter, int size);\n\n/**\n * Track the presence of user provided functions and their number of occurrences\n * in a parsed expression.\n *\n * @param counter a zero-initialized array where the count of each function will be stored\n *                if you passed 5 functions with 2 arguments to av_expr_parse()\n *                then for arg=2 this will use upto 5 entries.\n * @param size size of array\n * @param arg number of arguments the counted functions have\n * @return 0 on success, a negative value indicates that no expression or array was passed\n * or size was zero\n */\nint av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg);\n\n/**\n * Free a parsed expression previously created with av_expr_parse().\n */\nvoid av_expr_free(AVExpr *e);\n\n/**\n * Parse the string in numstr and return its value as a double. If\n * the string is empty, contains only whitespaces, or does not contain\n * an initial substring that has the expected syntax for a\n * floating-point number, no conversion is performed. In this case,\n * returns a value of zero and the value returned in tail is the value\n * of numstr.\n *\n * @param numstr a string representing a number, may contain one of\n * the International System number postfixes, for example 'K', 'M',\n * 'G'. If 'i' is appended after the postfix, powers of 2 are used\n * instead of powers of 10. The 'B' postfix multiplies the value by\n * 8, and can be appended after another postfix or used alone. This\n * allows using for example 'KB', 'MiB', 'G' and 'B' as postfix.\n * @param tail if non-NULL puts here the pointer to the char next\n * after the last parsed character\n */\ndouble av_strtod(const char *numstr, char **tail);\n\n#endif /* AVUTIL_EVAL_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/ffversion.h",
    "content": "/* Automatically generated by version.sh, do not manually edit! */\n#ifndef AVUTIL_FFVERSION_H\n#define AVUTIL_FFVERSION_H\n#define FFMPEG_VERSION \"5.1.2-full_build-www.gyan.dev\"\n#endif /* AVUTIL_FFVERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/fifo.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * a very simple circular buffer FIFO implementation\n */\n\n#ifndef AVUTIL_FIFO_H\n#define AVUTIL_FIFO_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"attributes.h\"\n#include \"version.h\"\n\ntypedef struct AVFifo AVFifo;\n\n/**\n * Callback for writing or reading from a FIFO, passed to (and invoked from) the\n * av_fifo_*_cb() functions. It may be invoked multiple times from a single\n * av_fifo_*_cb() call and may process less data than the maximum size indicated\n * by nb_elems.\n *\n * @param opaque the opaque pointer provided to the av_fifo_*_cb() function\n * @param buf the buffer for reading or writing the data, depending on which\n *            av_fifo_*_cb function is called\n * @param nb_elems On entry contains the maximum number of elements that can be\n *                 read from / written into buf. On success, the callback should\n *                 update it to contain the number of elements actually written.\n *\n * @return 0 on success, a negative error code on failure (will be returned from\n *         the invoking av_fifo_*_cb() function)\n */\ntypedef int AVFifoCB(void *opaque, void *buf, size_t *nb_elems);\n\n/**\n * Automatically resize the FIFO on writes, so that the data fits. This\n * automatic resizing happens up to a limit that can be modified with\n * av_fifo_auto_grow_limit().\n */\n#define AV_FIFO_FLAG_AUTO_GROW      (1 << 0)\n\n/**\n * Allocate and initialize an AVFifo with a given element size.\n *\n * @param elems     initial number of elements that can be stored in the FIFO\n * @param elem_size Size in bytes of a single element. Further operations on\n *                  the returned FIFO will implicitly use this element size.\n * @param flags a combination of AV_FIFO_FLAG_*\n *\n * @return newly-allocated AVFifo on success, a negative error code on failure\n */\nAVFifo *av_fifo_alloc2(size_t elems, size_t elem_size,\n                       unsigned int flags);\n\n/**\n * @return Element size for FIFO operations. This element size is set at\n *         FIFO allocation and remains constant during its lifetime\n */\nsize_t av_fifo_elem_size(const AVFifo *f);\n\n/**\n * Set the maximum size (in elements) to which the FIFO can be resized\n * automatically. Has no effect unless AV_FIFO_FLAG_AUTO_GROW is used.\n */\nvoid av_fifo_auto_grow_limit(AVFifo *f, size_t max_elems);\n\n/**\n * @return number of elements available for reading from the given FIFO.\n */\nsize_t av_fifo_can_read(const AVFifo *f);\n\n/**\n * @return number of elements that can be written into the given FIFO.\n */\nsize_t av_fifo_can_write(const AVFifo *f);\n\n/**\n * Enlarge an AVFifo.\n *\n * On success, the FIFO will be large enough to hold exactly\n * inc + av_fifo_can_read() + av_fifo_can_write()\n * elements. In case of failure, the old FIFO is kept unchanged.\n *\n * @param f AVFifo to resize\n * @param inc number of elements to allocate for, in addition to the current\n *            allocated size\n * @return a non-negative number on success, a negative error code on failure\n */\nint av_fifo_grow2(AVFifo *f, size_t inc);\n\n/**\n * Write data into a FIFO.\n *\n * In case nb_elems > av_fifo_can_write(f), nothing is written and an error\n * is returned.\n *\n * @param f the FIFO buffer\n * @param buf Data to be written. nb_elems * av_fifo_elem_size(f) bytes will be\n *            read from buf on success.\n * @param nb_elems number of elements to write into FIFO\n *\n * @return a non-negative number on success, a negative error code on failure\n */\nint av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems);\n\n/**\n * Write data from a user-provided callback into a FIFO.\n *\n * @param f the FIFO buffer\n * @param read_cb Callback supplying the data to the FIFO. May be called\n *                multiple times.\n * @param opaque opaque user data to be provided to read_cb\n * @param nb_elems Should point to the maximum number of elements that can be\n *                 written. Will be updated to contain the number of elements\n *                 actually written.\n *\n * @return non-negative number on success, a negative error code on failure\n */\nint av_fifo_write_from_cb(AVFifo *f, AVFifoCB read_cb,\n                          void *opaque, size_t *nb_elems);\n\n/**\n * Read data from a FIFO.\n *\n * In case nb_elems > av_fifo_can_read(f), nothing is read and an error\n * is returned.\n *\n * @param f the FIFO buffer\n * @param buf Buffer to store the data. nb_elems * av_fifo_elem_size(f) bytes\n *            will be written into buf on success.\n * @param nb_elems number of elements to read from FIFO\n *\n * @return a non-negative number on success, a negative error code on failure\n */\nint av_fifo_read(AVFifo *f, void *buf, size_t nb_elems);\n\n/**\n * Feed data from a FIFO into a user-provided callback.\n *\n * @param f the FIFO buffer\n * @param write_cb Callback the data will be supplied to. May be called\n *                 multiple times.\n * @param opaque opaque user data to be provided to write_cb\n * @param nb_elems Should point to the maximum number of elements that can be\n *                 read. Will be updated to contain the total number of elements\n *                 actually sent to the callback.\n *\n * @return non-negative number on success, a negative error code on failure\n */\nint av_fifo_read_to_cb(AVFifo *f, AVFifoCB write_cb,\n                       void *opaque, size_t *nb_elems);\n\n/**\n * Read data from a FIFO without modifying FIFO state.\n *\n * Returns an error if an attempt is made to peek to nonexistent elements\n * (i.e. if offset + nb_elems is larger than av_fifo_can_read(f)).\n *\n * @param f the FIFO buffer\n * @param buf Buffer to store the data. nb_elems * av_fifo_elem_size(f) bytes\n *            will be written into buf.\n * @param nb_elems number of elements to read from FIFO\n * @param offset number of initial elements to skip.\n *\n * @return a non-negative number on success, a negative error code on failure\n */\nint av_fifo_peek(AVFifo *f, void *buf, size_t nb_elems, size_t offset);\n\n/**\n * Feed data from a FIFO into a user-provided callback.\n *\n * @param f the FIFO buffer\n * @param write_cb Callback the data will be supplied to. May be called\n *                 multiple times.\n * @param opaque opaque user data to be provided to write_cb\n * @param nb_elems Should point to the maximum number of elements that can be\n *                 read. Will be updated to contain the total number of elements\n *                 actually sent to the callback.\n * @param offset number of initial elements to skip; offset + *nb_elems must not\n *               be larger than av_fifo_can_read(f).\n *\n * @return a non-negative number on success, a negative error code on failure\n */\nint av_fifo_peek_to_cb(AVFifo *f, AVFifoCB write_cb, void *opaque,\n                       size_t *nb_elems, size_t offset);\n\n/**\n * Discard the specified amount of data from an AVFifo.\n * @param size number of elements to discard, MUST NOT be larger than\n *             av_fifo_can_read(f)\n */\nvoid av_fifo_drain2(AVFifo *f, size_t size);\n\n/*\n * Empty the AVFifo.\n * @param f AVFifo to reset\n */\nvoid av_fifo_reset2(AVFifo *f);\n\n/**\n * Free an AVFifo and reset pointer to NULL.\n * @param f Pointer to an AVFifo to free. *f == NULL is allowed.\n */\nvoid av_fifo_freep2(AVFifo **f);\n\n\n#if FF_API_FIFO_OLD_API\ntypedef struct AVFifoBuffer {\n    uint8_t *buffer;\n    uint8_t *rptr, *wptr, *end;\n    uint32_t rndx, wndx;\n} AVFifoBuffer;\n\n/**\n * Initialize an AVFifoBuffer.\n * @param size of FIFO\n * @return AVFifoBuffer or NULL in case of memory allocation failure\n * @deprecated use av_fifo_alloc2()\n */\nattribute_deprecated\nAVFifoBuffer *av_fifo_alloc(unsigned int size);\n\n/**\n * Initialize an AVFifoBuffer.\n * @param nmemb number of elements\n * @param size  size of the single element\n * @return AVFifoBuffer or NULL in case of memory allocation failure\n * @deprecated use av_fifo_alloc2()\n */\nattribute_deprecated\nAVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size);\n\n/**\n * Free an AVFifoBuffer.\n * @param f AVFifoBuffer to free\n * @deprecated use the AVFifo API with av_fifo_freep2()\n */\nattribute_deprecated\nvoid av_fifo_free(AVFifoBuffer *f);\n\n/**\n * Free an AVFifoBuffer and reset pointer to NULL.\n * @param f AVFifoBuffer to free\n * @deprecated use the AVFifo API with av_fifo_freep2()\n */\nattribute_deprecated\nvoid av_fifo_freep(AVFifoBuffer **f);\n\n/**\n * Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied.\n * @param f AVFifoBuffer to reset\n * @deprecated use av_fifo_reset2() with the new AVFifo-API\n */\nattribute_deprecated\nvoid av_fifo_reset(AVFifoBuffer *f);\n\n/**\n * Return the amount of data in bytes in the AVFifoBuffer, that is the\n * amount of data you can read from it.\n * @param f AVFifoBuffer to read from\n * @return size\n * @deprecated use av_fifo_can_read() with the new AVFifo-API\n */\nattribute_deprecated\nint av_fifo_size(const AVFifoBuffer *f);\n\n/**\n * Return the amount of space in bytes in the AVFifoBuffer, that is the\n * amount of data you can write into it.\n * @param f AVFifoBuffer to write into\n * @return size\n * @deprecated use av_fifo_can_write() with the new AVFifo-API\n */\nattribute_deprecated\nint av_fifo_space(const AVFifoBuffer *f);\n\n/**\n * Feed data at specific position from an AVFifoBuffer to a user-supplied callback.\n * Similar as av_fifo_gereric_read but without discarding data.\n * @param f AVFifoBuffer to read from\n * @param offset offset from current read position\n * @param buf_size number of bytes to read\n * @param func generic read function\n * @param dest data destination\n *\n * @return a non-negative number on success, a negative error code on failure\n *\n * @deprecated use the new AVFifo-API with av_fifo_peek() when func == NULL,\n *             av_fifo_peek_to_cb() otherwise\n */\nattribute_deprecated\nint av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int));\n\n/**\n * Feed data from an AVFifoBuffer to a user-supplied callback.\n * Similar as av_fifo_gereric_read but without discarding data.\n * @param f AVFifoBuffer to read from\n * @param buf_size number of bytes to read\n * @param func generic read function\n * @param dest data destination\n *\n * @return a non-negative number on success, a negative error code on failure\n *\n * @deprecated use the new AVFifo-API with av_fifo_peek() when func == NULL,\n *             av_fifo_peek_to_cb() otherwise\n */\nattribute_deprecated\nint av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int));\n\n/**\n * Feed data from an AVFifoBuffer to a user-supplied callback.\n * @param f AVFifoBuffer to read from\n * @param buf_size number of bytes to read\n * @param func generic read function\n * @param dest data destination\n *\n * @return a non-negative number on success, a negative error code on failure\n *\n * @deprecated use the new AVFifo-API with av_fifo_read() when func == NULL,\n *             av_fifo_read_to_cb() otherwise\n */\nattribute_deprecated\nint av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int));\n\n/**\n * Feed data from a user-supplied callback to an AVFifoBuffer.\n * @param f AVFifoBuffer to write to\n * @param src data source; non-const since it may be used as a\n * modifiable context by the function defined in func\n * @param size number of bytes to write\n * @param func generic write function; the first parameter is src,\n * the second is dest_buf, the third is dest_buf_size.\n * func must return the number of bytes written to dest_buf, or <= 0 to\n * indicate no more data available to write.\n * If func is NULL, src is interpreted as a simple byte array for source data.\n * @return the number of bytes written to the FIFO or a negative error code on failure\n *\n * @deprecated use the new AVFifo-API with av_fifo_write() when func == NULL,\n *             av_fifo_write_from_cb() otherwise\n */\nattribute_deprecated\nint av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int));\n\n/**\n * Resize an AVFifoBuffer.\n * In case of reallocation failure, the old FIFO is kept unchanged.\n *\n * @param f AVFifoBuffer to resize\n * @param size new AVFifoBuffer size in bytes\n * @return <0 for failure, >=0 otherwise\n *\n * @deprecated use the new AVFifo-API with av_fifo_grow2() to increase FIFO size,\n *             decreasing FIFO size is not supported\n */\nattribute_deprecated\nint av_fifo_realloc2(AVFifoBuffer *f, unsigned int size);\n\n/**\n * Enlarge an AVFifoBuffer.\n * In case of reallocation failure, the old FIFO is kept unchanged.\n * The new fifo size may be larger than the requested size.\n *\n * @param f AVFifoBuffer to resize\n * @param additional_space the amount of space in bytes to allocate in addition to av_fifo_size()\n * @return <0 for failure, >=0 otherwise\n *\n * @deprecated use the new AVFifo-API with av_fifo_grow2(); note that unlike\n * this function it adds to the allocated size, rather than to the used size\n */\nattribute_deprecated\nint av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space);\n\n/**\n * Read and discard the specified amount of data from an AVFifoBuffer.\n * @param f AVFifoBuffer to read from\n * @param size amount of data to read in bytes\n *\n * @deprecated use the new AVFifo-API with av_fifo_drain2()\n */\nattribute_deprecated\nvoid av_fifo_drain(AVFifoBuffer *f, int size);\n\n#if FF_API_FIFO_PEEK2\n/**\n * Return a pointer to the data stored in a FIFO buffer at a certain offset.\n * The FIFO buffer is not modified.\n *\n * @param f    AVFifoBuffer to peek at, f must be non-NULL\n * @param offs an offset in bytes, its absolute value must be less\n *             than the used buffer size or the returned pointer will\n *             point outside to the buffer data.\n *             The used buffer size can be checked with av_fifo_size().\n * @deprecated use the new AVFifo-API with av_fifo_peek() or av_fifo_peek_to_cb()\n */\nattribute_deprecated\nstatic inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs)\n{\n    uint8_t *ptr = f->rptr + offs;\n    if (ptr >= f->end)\n        ptr = f->buffer + (ptr - f->end);\n    else if (ptr < f->buffer)\n        ptr = f->end - (f->buffer - ptr);\n    return ptr;\n}\n#endif\n#endif\n\n#endif /* AVUTIL_FIFO_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/file.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_FILE_H\n#define AVUTIL_FILE_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"attributes.h\"\n\n/**\n * @file\n * Misc file utilities.\n */\n\n/**\n * Read the file with name filename, and put its content in a newly\n * allocated buffer or map it with mmap() when available.\n * In case of success set *bufptr to the read or mmapped buffer, and\n * *size to the size in bytes of the buffer in *bufptr.\n * Unlike mmap this function succeeds with zero sized files, in this\n * case *bufptr will be set to NULL and *size will be set to 0.\n * The returned buffer must be released with av_file_unmap().\n *\n * @param log_offset loglevel offset used for logging\n * @param log_ctx context used for logging\n * @return a non negative number in case of success, a negative value\n * corresponding to an AVERROR error code in case of failure\n */\nav_warn_unused_result\nint av_file_map(const char *filename, uint8_t **bufptr, size_t *size,\n                int log_offset, void *log_ctx);\n\n/**\n * Unmap or free the buffer bufptr created by av_file_map().\n *\n * @param size size in bytes of bufptr, must be the same as returned\n * by av_file_map()\n */\nvoid av_file_unmap(uint8_t *bufptr, size_t size);\n\n/**\n * Wrapper to work around the lack of mkstemp() on mingw.\n * Also, tries to create file in /tmp first, if possible.\n * *prefix can be a character constant; *filename will be allocated internally.\n * @return file descriptor of opened file (or negative value corresponding to an\n * AVERROR code on error)\n * and opened file name in **filename.\n * @note On very old libcs it is necessary to set a secure umask before\n *       calling this, av_tempfile() can't call umask itself as it is used in\n *       libraries and could interfere with the calling application.\n * @deprecated as fd numbers cannot be passed saftely between libs on some platforms\n */\nint av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx);\n\n#endif /* AVUTIL_FILE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/film_grain_params.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_FILM_GRAIN_PARAMS_H\n#define AVUTIL_FILM_GRAIN_PARAMS_H\n\n#include \"frame.h\"\n\nenum AVFilmGrainParamsType {\n    AV_FILM_GRAIN_PARAMS_NONE = 0,\n\n    /**\n     * The union is valid when interpreted as AVFilmGrainAOMParams (codec.aom)\n     */\n    AV_FILM_GRAIN_PARAMS_AV1,\n\n    /**\n     * The union is valid when interpreted as AVFilmGrainH274Params (codec.h274)\n     */\n    AV_FILM_GRAIN_PARAMS_H274,\n};\n\n/**\n * This structure describes how to handle film grain synthesis for AOM codecs.\n *\n * @note The struct must be allocated as part of AVFilmGrainParams using\n *       av_film_grain_params_alloc(). Its size is not a part of the public ABI.\n */\ntypedef struct AVFilmGrainAOMParams {\n    /**\n     * Number of points, and the scale and value for each point of the\n     * piecewise linear scaling function for the uma plane.\n     */\n    int num_y_points;\n    uint8_t y_points[14][2 /* value, scaling */];\n\n    /**\n     * Signals whether to derive the chroma scaling function from the luma.\n     * Not equivalent to copying the luma values and scales.\n     */\n    int chroma_scaling_from_luma;\n\n    /**\n     * If chroma_scaling_from_luma is set to 0, signals the chroma scaling\n     * function parameters.\n     */\n    int num_uv_points[2 /* cb, cr */];\n    uint8_t uv_points[2 /* cb, cr */][10][2 /* value, scaling */];\n\n    /**\n     * Specifies the shift applied to the chroma components. For AV1, its within\n     * [8; 11] and determines the range and quantization of the film grain.\n     */\n    int scaling_shift;\n\n    /**\n     * Specifies the auto-regression lag.\n     */\n    int ar_coeff_lag;\n\n    /**\n     * Luma auto-regression coefficients. The number of coefficients is given by\n     * 2 * ar_coeff_lag * (ar_coeff_lag + 1).\n     */\n    int8_t ar_coeffs_y[24];\n\n    /**\n     * Chroma auto-regression coefficients. The number of coefficients is given by\n     * 2 * ar_coeff_lag * (ar_coeff_lag + 1) + !!num_y_points.\n     */\n    int8_t ar_coeffs_uv[2 /* cb, cr */][25];\n\n    /**\n     * Specifies the range of the auto-regressive coefficients. Values of 6,\n     * 7, 8 and so on represent a range of [-2, 2), [-1, 1), [-0.5, 0.5) and\n     * so on. For AV1 must be between 6 and 9.\n     */\n    int ar_coeff_shift;\n\n    /**\n     * Signals the down shift applied to the generated gaussian numbers during\n     * synthesis.\n     */\n    int grain_scale_shift;\n\n    /**\n     * Specifies the luma/chroma multipliers for the index to the component\n     * scaling function.\n     */\n    int uv_mult[2 /* cb, cr */];\n    int uv_mult_luma[2 /* cb, cr */];\n\n    /**\n     * Offset used for component scaling function. For AV1 its a 9-bit value\n     * with a range [-256, 255]\n     */\n    int uv_offset[2 /* cb, cr */];\n\n    /**\n     * Signals whether to overlap film grain blocks.\n     */\n    int overlap_flag;\n\n    /**\n     * Signals to clip to limited color levels after film grain application.\n     */\n    int limit_output_range;\n} AVFilmGrainAOMParams;\n\n/**\n * This structure describes how to handle film grain synthesis for codecs using\n * the ITU-T H.274 Versatile suplemental enhancement information message.\n *\n * @note The struct must be allocated as part of AVFilmGrainParams using\n *       av_film_grain_params_alloc(). Its size is not a part of the public ABI.\n */\ntypedef struct AVFilmGrainH274Params {\n    /**\n     * Specifies the film grain simulation mode.\n     * 0 = Frequency filtering, 1 = Auto-regression\n     */\n    int model_id;\n\n    /**\n     * Specifies the bit depth used for the luma component.\n     */\n    int bit_depth_luma;\n\n    /**\n     * Specifies the bit depth used for the chroma components.\n     */\n    int bit_depth_chroma;\n\n    enum AVColorRange                  color_range;\n    enum AVColorPrimaries              color_primaries;\n    enum AVColorTransferCharacteristic color_trc;\n    enum AVColorSpace                  color_space;\n\n    /**\n     * Specifies the blending mode used to blend the simulated film grain\n     * with the decoded images.\n     *\n     * 0 = Additive, 1 = Multiplicative\n     */\n    int blending_mode_id;\n\n    /**\n     * Specifies a scale factor used in the film grain characterization equations.\n     */\n    int log2_scale_factor;\n\n    /**\n     * Indicates if the modelling of film grain for a given component is present.\n     */\n    int component_model_present[3 /* y, cb, cr */];\n\n    /**\n     * Specifies the number of intensity intervals for which a specific set of\n     * model values has been estimated, with a range of [1, 256].\n     */\n    uint16_t num_intensity_intervals[3 /* y, cb, cr */];\n\n    /**\n     * Specifies the number of model values present for each intensity interval\n     * in which the film grain has been modelled, with a range of [1, 6].\n     */\n    uint8_t num_model_values[3 /* y, cb, cr */];\n\n    /**\n     * Specifies the lower ounds of each intensity interval for whichthe set of\n     * model values applies for the component.\n     */\n    uint8_t intensity_interval_lower_bound[3 /* y, cb, cr */][256 /* intensity interval */];\n\n    /**\n     * Specifies the upper bound of each intensity interval for which the set of\n     * model values applies for the component.\n     */\n    uint8_t intensity_interval_upper_bound[3 /* y, cb, cr */][256 /* intensity interval */];\n\n    /**\n     * Specifies the model values for the component for each intensity interval.\n     * - When model_id == 0, the following applies:\n     *     For comp_model_value[y], the range of values is [0, 2^bit_depth_luma - 1]\n     *     For comp_model_value[cb..cr], the range of values is [0, 2^bit_depth_chroma - 1]\n     * - Otherwise, the following applies:\n     *     For comp_model_value[y], the range of values is [-2^(bit_depth_luma - 1), 2^(bit_depth_luma - 1) - 1]\n     *     For comp_model_value[cb..cr], the range of values is [-2^(bit_depth_chroma - 1), 2^(bit_depth_chroma - 1) - 1]\n     */\n    int16_t comp_model_value[3 /* y, cb, cr */][256 /* intensity interval */][6 /* model value */];\n} AVFilmGrainH274Params;\n\n/**\n * This structure describes how to handle film grain synthesis in video\n * for specific codecs. Must be present on every frame where film grain is\n * meant to be synthesised for correct presentation.\n *\n * @note The struct must be allocated with av_film_grain_params_alloc() and\n *       its size is not a part of the public ABI.\n */\ntypedef struct AVFilmGrainParams {\n    /**\n     * Specifies the codec for which this structure is valid.\n     */\n    enum AVFilmGrainParamsType type;\n\n    /**\n     * Seed to use for the synthesis process, if the codec allows for it.\n     *\n     * @note For H.264, this refers to `pic_offset` as defined in\n     *       SMPTE RDD 5-2006.\n     */\n    uint64_t seed;\n\n    /**\n     * Additional fields may be added both here and in any structure included.\n     * If a codec's film grain structure differs slightly over another\n     * codec's, fields within may change meaning depending on the type.\n     */\n    union {\n        AVFilmGrainAOMParams aom;\n        AVFilmGrainH274Params h274;\n    } codec;\n} AVFilmGrainParams;\n\n/**\n * Allocate an AVFilmGrainParams structure and set its fields to\n * default values. The resulting struct can be freed using av_freep().\n * If size is not NULL it will be set to the number of bytes allocated.\n *\n * @return An AVFilmGrainParams filled with default values or NULL\n *         on failure.\n */\nAVFilmGrainParams *av_film_grain_params_alloc(size_t *size);\n\n/**\n * Allocate a complete AVFilmGrainParams and add it to the frame.\n *\n * @param frame The frame which side data is added to.\n *\n * @return The AVFilmGrainParams structure to be filled by caller.\n */\nAVFilmGrainParams *av_film_grain_params_create_side_data(AVFrame *frame);\n\n#endif /* AVUTIL_FILM_GRAIN_PARAMS_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/frame.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_frame\n * reference-counted frame API\n */\n\n#ifndef AVUTIL_FRAME_H\n#define AVUTIL_FRAME_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"avutil.h\"\n#include \"buffer.h\"\n#include \"channel_layout.h\"\n#include \"dict.h\"\n#include \"rational.h\"\n#include \"samplefmt.h\"\n#include \"pixfmt.h\"\n#include \"version.h\"\n\n\n/**\n * @defgroup lavu_frame AVFrame\n * @ingroup lavu_data\n *\n * @{\n * AVFrame is an abstraction for reference-counted raw multimedia data.\n */\n\nenum AVFrameSideDataType {\n    /**\n     * The data is the AVPanScan struct defined in libavcodec.\n     */\n    AV_FRAME_DATA_PANSCAN,\n    /**\n     * ATSC A53 Part 4 Closed Captions.\n     * A53 CC bitstream is stored as uint8_t in AVFrameSideData.data.\n     * The number of bytes of CC data is AVFrameSideData.size.\n     */\n    AV_FRAME_DATA_A53_CC,\n    /**\n     * Stereoscopic 3d metadata.\n     * The data is the AVStereo3D struct defined in libavutil/stereo3d.h.\n     */\n    AV_FRAME_DATA_STEREO3D,\n    /**\n     * The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h.\n     */\n    AV_FRAME_DATA_MATRIXENCODING,\n    /**\n     * Metadata relevant to a downmix procedure.\n     * The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h.\n     */\n    AV_FRAME_DATA_DOWNMIX_INFO,\n    /**\n     * ReplayGain information in the form of the AVReplayGain struct.\n     */\n    AV_FRAME_DATA_REPLAYGAIN,\n    /**\n     * This side data contains a 3x3 transformation matrix describing an affine\n     * transformation that needs to be applied to the frame for correct\n     * presentation.\n     *\n     * See libavutil/display.h for a detailed description of the data.\n     */\n    AV_FRAME_DATA_DISPLAYMATRIX,\n    /**\n     * Active Format Description data consisting of a single byte as specified\n     * in ETSI TS 101 154 using AVActiveFormatDescription enum.\n     */\n    AV_FRAME_DATA_AFD,\n    /**\n     * Motion vectors exported by some codecs (on demand through the export_mvs\n     * flag set in the libavcodec AVCodecContext flags2 option).\n     * The data is the AVMotionVector struct defined in\n     * libavutil/motion_vector.h.\n     */\n    AV_FRAME_DATA_MOTION_VECTORS,\n    /**\n     * Recommmends skipping the specified number of samples. This is exported\n     * only if the \"skip_manual\" AVOption is set in libavcodec.\n     * This has the same format as AV_PKT_DATA_SKIP_SAMPLES.\n     * @code\n     * u32le number of samples to skip from start of this packet\n     * u32le number of samples to skip from end of this packet\n     * u8    reason for start skip\n     * u8    reason for end   skip (0=padding silence, 1=convergence)\n     * @endcode\n     */\n    AV_FRAME_DATA_SKIP_SAMPLES,\n    /**\n     * This side data must be associated with an audio frame and corresponds to\n     * enum AVAudioServiceType defined in avcodec.h.\n     */\n    AV_FRAME_DATA_AUDIO_SERVICE_TYPE,\n    /**\n     * Mastering display metadata associated with a video frame. The payload is\n     * an AVMasteringDisplayMetadata type and contains information about the\n     * mastering display color volume.\n     */\n    AV_FRAME_DATA_MASTERING_DISPLAY_METADATA,\n    /**\n     * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer.\n     * This is set on the first frame of a GOP that has a temporal reference of 0.\n     */\n    AV_FRAME_DATA_GOP_TIMECODE,\n\n    /**\n     * The data represents the AVSphericalMapping structure defined in\n     * libavutil/spherical.h.\n     */\n    AV_FRAME_DATA_SPHERICAL,\n\n    /**\n     * Content light level (based on CTA-861.3). This payload contains data in\n     * the form of the AVContentLightMetadata struct.\n     */\n    AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,\n\n    /**\n     * The data contains an ICC profile as an opaque octet buffer following the\n     * format described by ISO 15076-1 with an optional name defined in the\n     * metadata key entry \"name\".\n     */\n    AV_FRAME_DATA_ICC_PROFILE,\n\n    /**\n     * Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t\n     * where the first uint32_t describes how many (1-3) of the other timecodes are used.\n     * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum()\n     * function in libavutil/timecode.h.\n     */\n    AV_FRAME_DATA_S12M_TIMECODE,\n\n    /**\n     * HDR dynamic metadata associated with a video frame. The payload is\n     * an AVDynamicHDRPlus type and contains information for color\n     * volume transform - application 4 of SMPTE 2094-40:2016 standard.\n     */\n    AV_FRAME_DATA_DYNAMIC_HDR_PLUS,\n\n    /**\n     * Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of\n     * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size.\n     */\n    AV_FRAME_DATA_REGIONS_OF_INTEREST,\n\n    /**\n     * Encoding parameters for a video frame, as described by AVVideoEncParams.\n     */\n    AV_FRAME_DATA_VIDEO_ENC_PARAMS,\n\n    /**\n     * User data unregistered metadata associated with a video frame.\n     * This is the H.26[45] UDU SEI message, and shouldn't be used for any other purpose\n     * The data is stored as uint8_t in AVFrameSideData.data which is 16 bytes of\n     * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte.\n     */\n    AV_FRAME_DATA_SEI_UNREGISTERED,\n\n    /**\n     * Film grain parameters for a frame, described by AVFilmGrainParams.\n     * Must be present for every frame which should have film grain applied.\n     */\n    AV_FRAME_DATA_FILM_GRAIN_PARAMS,\n\n    /**\n     * Bounding boxes for object detection and classification,\n     * as described by AVDetectionBBoxHeader.\n     */\n    AV_FRAME_DATA_DETECTION_BBOXES,\n\n    /**\n     * Dolby Vision RPU raw data, suitable for passing to x265\n     * or other libraries. Array of uint8_t, with NAL emulation\n     * bytes intact.\n     */\n    AV_FRAME_DATA_DOVI_RPU_BUFFER,\n\n    /**\n     * Parsed Dolby Vision metadata, suitable for passing to a software\n     * implementation. The payload is the AVDOVIMetadata struct defined in\n     * libavutil/dovi_meta.h.\n     */\n    AV_FRAME_DATA_DOVI_METADATA,\n\n    /**\n     * HDR Vivid dynamic metadata associated with a video frame. The payload is\n     * an AVDynamicHDRVivid type and contains information for color\n     * volume transform - CUVA 005.1-2021.\n     */\n    AV_FRAME_DATA_DYNAMIC_HDR_VIVID,\n};\n\nenum AVActiveFormatDescription {\n    AV_AFD_SAME         = 8,\n    AV_AFD_4_3          = 9,\n    AV_AFD_16_9         = 10,\n    AV_AFD_14_9         = 11,\n    AV_AFD_4_3_SP_14_9  = 13,\n    AV_AFD_16_9_SP_14_9 = 14,\n    AV_AFD_SP_4_3       = 15,\n};\n\n\n/**\n * Structure to hold side data for an AVFrame.\n *\n * sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added\n * to the end with a minor bump.\n */\ntypedef struct AVFrameSideData {\n    enum AVFrameSideDataType type;\n    uint8_t *data;\n    size_t   size;\n    AVDictionary *metadata;\n    AVBufferRef *buf;\n} AVFrameSideData;\n\n/**\n * Structure describing a single Region Of Interest.\n *\n * When multiple regions are defined in a single side-data block, they\n * should be ordered from most to least important - some encoders are only\n * capable of supporting a limited number of distinct regions, so will have\n * to truncate the list.\n *\n * When overlapping regions are defined, the first region containing a given\n * area of the frame applies.\n */\ntypedef struct AVRegionOfInterest {\n    /**\n     * Must be set to the size of this data structure (that is,\n     * sizeof(AVRegionOfInterest)).\n     */\n    uint32_t self_size;\n    /**\n     * Distance in pixels from the top edge of the frame to the top and\n     * bottom edges and from the left edge of the frame to the left and\n     * right edges of the rectangle defining this region of interest.\n     *\n     * The constraints on a region are encoder dependent, so the region\n     * actually affected may be slightly larger for alignment or other\n     * reasons.\n     */\n    int top;\n    int bottom;\n    int left;\n    int right;\n    /**\n     * Quantisation offset.\n     *\n     * Must be in the range -1 to +1.  A value of zero indicates no quality\n     * change.  A negative value asks for better quality (less quantisation),\n     * while a positive value asks for worse quality (greater quantisation).\n     *\n     * The range is calibrated so that the extreme values indicate the\n     * largest possible offset - if the rest of the frame is encoded with the\n     * worst possible quality, an offset of -1 indicates that this region\n     * should be encoded with the best possible quality anyway.  Intermediate\n     * values are then interpolated in some codec-dependent way.\n     *\n     * For example, in 10-bit H.264 the quantisation parameter varies between\n     * -12 and 51.  A typical qoffset value of -1/10 therefore indicates that\n     * this region should be encoded with a QP around one-tenth of the full\n     * range better than the rest of the frame.  So, if most of the frame\n     * were to be encoded with a QP of around 30, this region would get a QP\n     * of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3).\n     * An extreme value of -1 would indicate that this region should be\n     * encoded with the best possible quality regardless of the treatment of\n     * the rest of the frame - that is, should be encoded at a QP of -12.\n     */\n    AVRational qoffset;\n} AVRegionOfInterest;\n\n/**\n * This structure describes decoded (raw) audio or video data.\n *\n * AVFrame must be allocated using av_frame_alloc(). Note that this only\n * allocates the AVFrame itself, the buffers for the data must be managed\n * through other means (see below).\n * AVFrame must be freed with av_frame_free().\n *\n * AVFrame is typically allocated once and then reused multiple times to hold\n * different data (e.g. a single AVFrame to hold frames received from a\n * decoder). In such a case, av_frame_unref() will free any references held by\n * the frame and reset it to its original clean state before it\n * is reused again.\n *\n * The data described by an AVFrame is usually reference counted through the\n * AVBuffer API. The underlying buffer references are stored in AVFrame.buf /\n * AVFrame.extended_buf. An AVFrame is considered to be reference counted if at\n * least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case,\n * every single data plane must be contained in one of the buffers in\n * AVFrame.buf or AVFrame.extended_buf.\n * There may be a single buffer for all the data, or one separate buffer for\n * each plane, or anything in between.\n *\n * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added\n * to the end with a minor bump.\n *\n * Fields can be accessed through AVOptions, the name string used, matches the\n * C structure field name for fields accessible through AVOptions. The AVClass\n * for AVFrame can be obtained from avcodec_get_frame_class()\n */\ntypedef struct AVFrame {\n#define AV_NUM_DATA_POINTERS 8\n    /**\n     * pointer to the picture/channel planes.\n     * This might be different from the first allocated byte. For video,\n     * it could even point to the end of the image data.\n     *\n     * All pointers in data and extended_data must point into one of the\n     * AVBufferRef in buf or extended_buf.\n     *\n     * Some decoders access areas outside 0,0 - width,height, please\n     * see avcodec_align_dimensions2(). Some filters and swscale can read\n     * up to 16 bytes beyond the planes, if these filters are to be used,\n     * then 16 extra bytes must be allocated.\n     *\n     * NOTE: Pointers not needed by the format MUST be set to NULL.\n     *\n     * @attention In case of video, the data[] pointers can point to the\n     * end of image data in order to reverse line order, when used in\n     * combination with negative values in the linesize[] array.\n     */\n    uint8_t *data[AV_NUM_DATA_POINTERS];\n\n    /**\n     * For video, a positive or negative value, which is typically indicating\n     * the size in bytes of each picture line, but it can also be:\n     * - the negative byte size of lines for vertical flipping\n     *   (with data[n] pointing to the end of the data\n     * - a positive or negative multiple of the byte size as for accessing\n     *   even and odd fields of a frame (possibly flipped)\n     *\n     * For audio, only linesize[0] may be set. For planar audio, each channel\n     * plane must be the same size.\n     *\n     * For video the linesizes should be multiples of the CPUs alignment\n     * preference, this is 16 or 32 for modern desktop CPUs.\n     * Some code requires such alignment other code can be slower without\n     * correct alignment, for yet other it makes no difference.\n     *\n     * @note The linesize may be larger than the size of usable data -- there\n     * may be extra padding present for performance reasons.\n     *\n     * @attention In case of video, line size values can be negative to achieve\n     * a vertically inverted iteration over image lines.\n     */\n    int linesize[AV_NUM_DATA_POINTERS];\n\n    /**\n     * pointers to the data planes/channels.\n     *\n     * For video, this should simply point to data[].\n     *\n     * For planar audio, each channel has a separate data pointer, and\n     * linesize[0] contains the size of each channel buffer.\n     * For packed audio, there is just one data pointer, and linesize[0]\n     * contains the total size of the buffer for all channels.\n     *\n     * Note: Both data and extended_data should always be set in a valid frame,\n     * but for planar audio with more channels that can fit in data,\n     * extended_data must be used in order to access all channels.\n     */\n    uint8_t **extended_data;\n\n    /**\n     * @name Video dimensions\n     * Video frames only. The coded dimensions (in pixels) of the video frame,\n     * i.e. the size of the rectangle that contains some well-defined values.\n     *\n     * @note The part of the frame intended for display/presentation is further\n     * restricted by the @ref cropping \"Cropping rectangle\".\n     * @{\n     */\n    int width, height;\n    /**\n     * @}\n     */\n\n    /**\n     * number of audio samples (per channel) described by this frame\n     */\n    int nb_samples;\n\n    /**\n     * format of the frame, -1 if unknown or unset\n     * Values correspond to enum AVPixelFormat for video frames,\n     * enum AVSampleFormat for audio)\n     */\n    int format;\n\n    /**\n     * 1 -> keyframe, 0-> not\n     */\n    int key_frame;\n\n    /**\n     * Picture type of the frame.\n     */\n    enum AVPictureType pict_type;\n\n    /**\n     * Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.\n     */\n    AVRational sample_aspect_ratio;\n\n    /**\n     * Presentation timestamp in time_base units (time when frame should be shown to user).\n     */\n    int64_t pts;\n\n    /**\n     * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used)\n     * This is also the Presentation time of this AVFrame calculated from\n     * only AVPacket.dts values without pts values.\n     */\n    int64_t pkt_dts;\n\n    /**\n     * Time base for the timestamps in this frame.\n     * In the future, this field may be set on frames output by decoders or\n     * filters, but its value will be by default ignored on input to encoders\n     * or filters.\n     */\n    AVRational time_base;\n\n    /**\n     * picture number in bitstream order\n     */\n    int coded_picture_number;\n    /**\n     * picture number in display order\n     */\n    int display_picture_number;\n\n    /**\n     * quality (between 1 (good) and FF_LAMBDA_MAX (bad))\n     */\n    int quality;\n\n    /**\n     * for some private data of the user\n     */\n    void *opaque;\n\n    /**\n     * When decoding, this signals how much the picture must be delayed.\n     * extra_delay = repeat_pict / (2*fps)\n     */\n    int repeat_pict;\n\n    /**\n     * The content of the picture is interlaced.\n     */\n    int interlaced_frame;\n\n    /**\n     * If the content is interlaced, is top field displayed first.\n     */\n    int top_field_first;\n\n    /**\n     * Tell user application that palette has changed from previous frame.\n     */\n    int palette_has_changed;\n\n    /**\n     * reordered opaque 64 bits (generally an integer or a double precision float\n     * PTS but can be anything).\n     * The user sets AVCodecContext.reordered_opaque to represent the input at\n     * that time,\n     * the decoder reorders values as needed and sets AVFrame.reordered_opaque\n     * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque\n     */\n    int64_t reordered_opaque;\n\n    /**\n     * Sample rate of the audio data.\n     */\n    int sample_rate;\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * Channel layout of the audio data.\n     * @deprecated use ch_layout instead\n     */\n    attribute_deprecated\n    uint64_t channel_layout;\n#endif\n\n    /**\n     * AVBuffer references backing the data for this frame. All the pointers in\n     * data and extended_data must point inside one of the buffers in buf or\n     * extended_buf. This array must be filled contiguously -- if buf[i] is\n     * non-NULL then buf[j] must also be non-NULL for all j < i.\n     *\n     * There may be at most one AVBuffer per data plane, so for video this array\n     * always contains all the references. For planar audio with more than\n     * AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in\n     * this array. Then the extra AVBufferRef pointers are stored in the\n     * extended_buf array.\n     */\n    AVBufferRef *buf[AV_NUM_DATA_POINTERS];\n\n    /**\n     * For planar audio which requires more than AV_NUM_DATA_POINTERS\n     * AVBufferRef pointers, this array will hold all the references which\n     * cannot fit into AVFrame.buf.\n     *\n     * Note that this is different from AVFrame.extended_data, which always\n     * contains all the pointers. This array only contains the extra pointers,\n     * which cannot fit into AVFrame.buf.\n     *\n     * This array is always allocated using av_malloc() by whoever constructs\n     * the frame. It is freed in av_frame_unref().\n     */\n    AVBufferRef **extended_buf;\n    /**\n     * Number of elements in extended_buf.\n     */\n    int        nb_extended_buf;\n\n    AVFrameSideData **side_data;\n    int            nb_side_data;\n\n/**\n * @defgroup lavu_frame_flags AV_FRAME_FLAGS\n * @ingroup lavu_frame\n * Flags describing additional frame properties.\n *\n * @{\n */\n\n/**\n * The frame data may be corrupted, e.g. due to decoding errors.\n */\n#define AV_FRAME_FLAG_CORRUPT       (1 << 0)\n/**\n * A flag to mark the frames which need to be decoded, but shouldn't be output.\n */\n#define AV_FRAME_FLAG_DISCARD   (1 << 2)\n/**\n * @}\n */\n\n    /**\n     * Frame flags, a combination of @ref lavu_frame_flags\n     */\n    int flags;\n\n    /**\n     * MPEG vs JPEG YUV range.\n     * - encoding: Set by user\n     * - decoding: Set by libavcodec\n     */\n    enum AVColorRange color_range;\n\n    enum AVColorPrimaries color_primaries;\n\n    enum AVColorTransferCharacteristic color_trc;\n\n    /**\n     * YUV colorspace type.\n     * - encoding: Set by user\n     * - decoding: Set by libavcodec\n     */\n    enum AVColorSpace colorspace;\n\n    enum AVChromaLocation chroma_location;\n\n    /**\n     * frame timestamp estimated using various heuristics, in stream time base\n     * - encoding: unused\n     * - decoding: set by libavcodec, read by user.\n     */\n    int64_t best_effort_timestamp;\n\n    /**\n     * reordered pos from the last AVPacket that has been input into the decoder\n     * - encoding: unused\n     * - decoding: Read by user.\n     */\n    int64_t pkt_pos;\n\n    /**\n     * duration of the corresponding packet, expressed in\n     * AVStream->time_base units, 0 if unknown.\n     * - encoding: unused\n     * - decoding: Read by user.\n     */\n    int64_t pkt_duration;\n\n    /**\n     * metadata.\n     * - encoding: Set by user.\n     * - decoding: Set by libavcodec.\n     */\n    AVDictionary *metadata;\n\n    /**\n     * decode error flags of the frame, set to a combination of\n     * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there\n     * were errors during the decoding.\n     * - encoding: unused\n     * - decoding: set by libavcodec, read by user.\n     */\n    int decode_error_flags;\n#define FF_DECODE_ERROR_INVALID_BITSTREAM   1\n#define FF_DECODE_ERROR_MISSING_REFERENCE   2\n#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE  4\n#define FF_DECODE_ERROR_DECODE_SLICES       8\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n    /**\n     * number of audio channels, only used for audio.\n     * - encoding: unused\n     * - decoding: Read by user.\n     * @deprecated use ch_layout instead\n     */\n    attribute_deprecated\n    int channels;\n#endif\n\n    /**\n     * size of the corresponding packet containing the compressed\n     * frame.\n     * It is set to a negative value if unknown.\n     * - encoding: unused\n     * - decoding: set by libavcodec, read by user.\n     */\n    int pkt_size;\n\n    /**\n     * For hwaccel-format frames, this should be a reference to the\n     * AVHWFramesContext describing the frame.\n     */\n    AVBufferRef *hw_frames_ctx;\n\n    /**\n     * AVBufferRef for free use by the API user. FFmpeg will never check the\n     * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when\n     * the frame is unreferenced. av_frame_copy_props() calls create a new\n     * reference with av_buffer_ref() for the target frame's opaque_ref field.\n     *\n     * This is unrelated to the opaque field, although it serves a similar\n     * purpose.\n     */\n    AVBufferRef *opaque_ref;\n\n    /**\n     * @anchor cropping\n     * @name Cropping\n     * Video frames only. The number of pixels to discard from the the\n     * top/bottom/left/right border of the frame to obtain the sub-rectangle of\n     * the frame intended for presentation.\n     * @{\n     */\n    size_t crop_top;\n    size_t crop_bottom;\n    size_t crop_left;\n    size_t crop_right;\n    /**\n     * @}\n     */\n\n    /**\n     * AVBufferRef for internal use by a single libav* library.\n     * Must not be used to transfer data between libraries.\n     * Has to be NULL when ownership of the frame leaves the respective library.\n     *\n     * Code outside the FFmpeg libs should never check or change the contents of the buffer ref.\n     *\n     * FFmpeg calls av_buffer_unref() on it when the frame is unreferenced.\n     * av_frame_copy_props() calls create a new reference with av_buffer_ref()\n     * for the target frame's private_ref field.\n     */\n    AVBufferRef *private_ref;\n\n    /**\n     * Channel layout of the audio data.\n     */\n    AVChannelLayout ch_layout;\n} AVFrame;\n\n\n#if FF_API_COLORSPACE_NAME\n/**\n * Get the name of a colorspace.\n * @return a static string identifying the colorspace; can be NULL.\n * @deprecated use av_color_space_name()\n */\nattribute_deprecated\nconst char *av_get_colorspace_name(enum AVColorSpace val);\n#endif\n/**\n * Allocate an AVFrame and set its fields to default values.  The resulting\n * struct must be freed using av_frame_free().\n *\n * @return An AVFrame filled with default values or NULL on failure.\n *\n * @note this only allocates the AVFrame itself, not the data buffers. Those\n * must be allocated through other means, e.g. with av_frame_get_buffer() or\n * manually.\n */\nAVFrame *av_frame_alloc(void);\n\n/**\n * Free the frame and any dynamically allocated objects in it,\n * e.g. extended_data. If the frame is reference counted, it will be\n * unreferenced first.\n *\n * @param frame frame to be freed. The pointer will be set to NULL.\n */\nvoid av_frame_free(AVFrame **frame);\n\n/**\n * Set up a new reference to the data described by the source frame.\n *\n * Copy frame properties from src to dst and create a new reference for each\n * AVBufferRef from src.\n *\n * If src is not reference counted, new buffers are allocated and the data is\n * copied.\n *\n * @warning: dst MUST have been either unreferenced with av_frame_unref(dst),\n *           or newly allocated with av_frame_alloc() before calling this\n *           function, or undefined behavior will occur.\n *\n * @return 0 on success, a negative AVERROR on error\n */\nint av_frame_ref(AVFrame *dst, const AVFrame *src);\n\n/**\n * Create a new frame that references the same data as src.\n *\n * This is a shortcut for av_frame_alloc()+av_frame_ref().\n *\n * @return newly created AVFrame on success, NULL on error.\n */\nAVFrame *av_frame_clone(const AVFrame *src);\n\n/**\n * Unreference all the buffers referenced by frame and reset the frame fields.\n */\nvoid av_frame_unref(AVFrame *frame);\n\n/**\n * Move everything contained in src to dst and reset src.\n *\n * @warning: dst is not unreferenced, but directly overwritten without reading\n *           or deallocating its contents. Call av_frame_unref(dst) manually\n *           before calling this function to ensure that no memory is leaked.\n */\nvoid av_frame_move_ref(AVFrame *dst, AVFrame *src);\n\n/**\n * Allocate new buffer(s) for audio or video data.\n *\n * The following fields must be set on frame before calling this function:\n * - format (pixel format for video, sample format for audio)\n * - width and height for video\n * - nb_samples and ch_layout for audio\n *\n * This function will fill AVFrame.data and AVFrame.buf arrays and, if\n * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf.\n * For planar formats, one buffer will be allocated for each plane.\n *\n * @warning: if frame already has been allocated, calling this function will\n *           leak memory. In addition, undefined behavior can occur in certain\n *           cases.\n *\n * @param frame frame in which to store the new buffers.\n * @param align Required buffer size alignment. If equal to 0, alignment will be\n *              chosen automatically for the current CPU. It is highly\n *              recommended to pass 0 here unless you know what you are doing.\n *\n * @return 0 on success, a negative AVERROR on error.\n */\nint av_frame_get_buffer(AVFrame *frame, int align);\n\n/**\n * Check if the frame data is writable.\n *\n * @return A positive value if the frame data is writable (which is true if and\n * only if each of the underlying buffers has only one reference, namely the one\n * stored in this frame). Return 0 otherwise.\n *\n * If 1 is returned the answer is valid until av_buffer_ref() is called on any\n * of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly).\n *\n * @see av_frame_make_writable(), av_buffer_is_writable()\n */\nint av_frame_is_writable(AVFrame *frame);\n\n/**\n * Ensure that the frame data is writable, avoiding data copy if possible.\n *\n * Do nothing if the frame is writable, allocate new buffers and copy the data\n * if it is not.\n *\n * @return 0 on success, a negative AVERROR on error.\n *\n * @see av_frame_is_writable(), av_buffer_is_writable(),\n * av_buffer_make_writable()\n */\nint av_frame_make_writable(AVFrame *frame);\n\n/**\n * Copy the frame data from src to dst.\n *\n * This function does not allocate anything, dst must be already initialized and\n * allocated with the same parameters as src.\n *\n * This function only copies the frame data (i.e. the contents of the data /\n * extended data arrays), not any other properties.\n *\n * @return >= 0 on success, a negative AVERROR on error.\n */\nint av_frame_copy(AVFrame *dst, const AVFrame *src);\n\n/**\n * Copy only \"metadata\" fields from src to dst.\n *\n * Metadata for the purpose of this function are those fields that do not affect\n * the data layout in the buffers.  E.g. pts, sample rate (for audio) or sample\n * aspect ratio (for video), but not width/height or channel layout.\n * Side data is also copied.\n */\nint av_frame_copy_props(AVFrame *dst, const AVFrame *src);\n\n/**\n * Get the buffer reference a given data plane is stored in.\n *\n * @param plane index of the data plane of interest in frame->extended_data.\n *\n * @return the buffer reference that contains the plane or NULL if the input\n * frame is not valid.\n */\nAVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane);\n\n/**\n * Add a new side data to a frame.\n *\n * @param frame a frame to which the side data should be added\n * @param type type of the added side data\n * @param size size of the side data\n *\n * @return newly added side data on success, NULL on error\n */\nAVFrameSideData *av_frame_new_side_data(AVFrame *frame,\n                                        enum AVFrameSideDataType type,\n                                        size_t size);\n\n/**\n * Add a new side data to a frame from an existing AVBufferRef\n *\n * @param frame a frame to which the side data should be added\n * @param type  the type of the added side data\n * @param buf   an AVBufferRef to add as side data. The ownership of\n *              the reference is transferred to the frame.\n *\n * @return newly added side data on success, NULL on error. On failure\n *         the frame is unchanged and the AVBufferRef remains owned by\n *         the caller.\n */\nAVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,\n                                                 enum AVFrameSideDataType type,\n                                                 AVBufferRef *buf);\n\n/**\n * @return a pointer to the side data of a given type on success, NULL if there\n * is no side data with such type in this frame.\n */\nAVFrameSideData *av_frame_get_side_data(const AVFrame *frame,\n                                        enum AVFrameSideDataType type);\n\n/**\n * Remove and free all side data instances of the given type.\n */\nvoid av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);\n\n\n/**\n * Flags for frame cropping.\n */\nenum {\n    /**\n     * Apply the maximum possible cropping, even if it requires setting the\n     * AVFrame.data[] entries to unaligned pointers. Passing unaligned data\n     * to FFmpeg API is generally not allowed, and causes undefined behavior\n     * (such as crashes). You can pass unaligned data only to FFmpeg APIs that\n     * are explicitly documented to accept it. Use this flag only if you\n     * absolutely know what you are doing.\n     */\n    AV_FRAME_CROP_UNALIGNED     = 1 << 0,\n};\n\n/**\n * Crop the given video AVFrame according to its crop_left/crop_top/crop_right/\n * crop_bottom fields. If cropping is successful, the function will adjust the\n * data pointers and the width/height fields, and set the crop fields to 0.\n *\n * In all cases, the cropping boundaries will be rounded to the inherent\n * alignment of the pixel format. In some cases, such as for opaque hwaccel\n * formats, the left/top cropping is ignored. The crop fields are set to 0 even\n * if the cropping was rounded or ignored.\n *\n * @param frame the frame which should be cropped\n * @param flags Some combination of AV_FRAME_CROP_* flags, or 0.\n *\n * @return >= 0 on success, a negative AVERROR on error. If the cropping fields\n * were invalid, AVERROR(ERANGE) is returned, and nothing is changed.\n */\nint av_frame_apply_cropping(AVFrame *frame, int flags);\n\n/**\n * @return a string identifying the side data type\n */\nconst char *av_frame_side_data_name(enum AVFrameSideDataType type);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_FRAME_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hash.h",
    "content": "/*\n * Copyright (C) 2013 Reimar Döffinger <Reimar.Doeffinger@gmx.de>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_hash_generic\n * Generic hashing API\n */\n\n#ifndef AVUTIL_HASH_H\n#define AVUTIL_HASH_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * @defgroup lavu_hash Hash Functions\n * @ingroup lavu_crypto\n * Hash functions useful in multimedia.\n *\n * Hash functions are widely used in multimedia, from error checking and\n * concealment to internal regression testing. libavutil has efficient\n * implementations of a variety of hash functions that may be useful for\n * FFmpeg and other multimedia applications.\n *\n * @{\n *\n * @defgroup lavu_hash_generic Generic Hashing API\n * An abstraction layer for all hash functions supported by libavutil.\n *\n * If your application needs to support a wide range of different hash\n * functions, then the Generic Hashing API is for you. It provides a generic,\n * reusable API for @ref lavu_hash \"all hash functions\" implemented in libavutil.\n * If you just need to use one particular hash function, use the @ref lavu_hash\n * \"individual hash\" directly.\n *\n * @section Sample Code\n *\n * A basic template for using the Generic Hashing API follows:\n *\n * @code\n * struct AVHashContext *ctx = NULL;\n * const char *hash_name = NULL;\n * uint8_t *output_buf = NULL;\n *\n * // Select from a string returned by av_hash_names()\n * hash_name = ...;\n *\n * // Allocate a hash context\n * ret = av_hash_alloc(&ctx, hash_name);\n * if (ret < 0)\n *     return ret;\n *\n * // Initialize the hash context\n * av_hash_init(ctx);\n *\n * // Update the hash context with data\n * while (data_left) {\n *     av_hash_update(ctx, data, size);\n * }\n *\n * // Now we have no more data, so it is time to finalize the hash and get the\n * // output. But we need to first allocate an output buffer. Note that you can\n * // use any memory allocation function, including malloc(), not just\n * // av_malloc().\n * output_buf = av_malloc(av_hash_get_size(ctx));\n * if (!output_buf)\n *     return AVERROR(ENOMEM);\n *\n * // Finalize the hash context.\n * // You can use any of the av_hash_final*() functions provided, for other\n * // output formats. If you do so, be sure to adjust the memory allocation\n * // above. See the function documentation below for the exact amount of extra\n * // memory needed.\n * av_hash_final(ctx, output_buffer);\n *\n * // Free the context\n * av_hash_freep(&ctx);\n * @endcode\n *\n * @section Hash Function-Specific Information\n * If the CRC32 hash is selected, the #AV_CRC_32_IEEE polynomial will be\n * used.\n *\n * If the Murmur3 hash is selected, the default seed will be used. See @ref\n * lavu_murmur3_seedinfo \"Murmur3\" for more information.\n *\n * @{\n */\n\n/**\n * @example ffhash.c\n * This example is a simple command line application that takes one or more\n * arguments. It demonstrates a typical use of the hashing API with allocation,\n * initialization, updating, and finalizing.\n */\n\nstruct AVHashContext;\n\n/**\n * Allocate a hash context for the algorithm specified by name.\n *\n * @return  >= 0 for success, a negative error code for failure\n *\n * @note The context is not initialized after a call to this function; you must\n * call av_hash_init() to do so.\n */\nint av_hash_alloc(struct AVHashContext **ctx, const char *name);\n\n/**\n * Get the names of available hash algorithms.\n *\n * This function can be used to enumerate the algorithms.\n *\n * @param[in] i  Index of the hash algorithm, starting from 0\n * @return       Pointer to a static string or `NULL` if `i` is out of range\n */\nconst char *av_hash_names(int i);\n\n/**\n * Get the name of the algorithm corresponding to the given hash context.\n */\nconst char *av_hash_get_name(const struct AVHashContext *ctx);\n\n/**\n * Maximum value that av_hash_get_size() will currently return.\n *\n * You can use this if you absolutely want or need to use static allocation for\n * the output buffer and are fine with not supporting hashes newly added to\n * libavutil without recompilation.\n *\n * @warning\n * Adding new hashes with larger sizes, and increasing the macro while doing\n * so, will not be considered an ABI change. To prevent your code from\n * overflowing a buffer, either dynamically allocate the output buffer with\n * av_hash_get_size(), or limit your use of the Hashing API to hashes that are\n * already in FFmpeg during the time of compilation.\n */\n#define AV_HASH_MAX_SIZE 64\n\n/**\n * Get the size of the resulting hash value in bytes.\n *\n * The maximum value this function will currently return is available as macro\n * #AV_HASH_MAX_SIZE.\n *\n * @param[in]     ctx Hash context\n * @return            Size of the hash value in bytes\n */\nint av_hash_get_size(const struct AVHashContext *ctx);\n\n/**\n * Initialize or reset a hash context.\n *\n * @param[in,out] ctx Hash context\n */\nvoid av_hash_init(struct AVHashContext *ctx);\n\n/**\n * Update a hash context with additional data.\n *\n * @param[in,out] ctx Hash context\n * @param[in]     src Data to be added to the hash context\n * @param[in]     len Size of the additional data\n */\nvoid av_hash_update(struct AVHashContext *ctx, const uint8_t *src, size_t len);\n\n/**\n * Finalize a hash context and compute the actual hash value.\n *\n * The minimum size of `dst` buffer is given by av_hash_get_size() or\n * #AV_HASH_MAX_SIZE. The use of the latter macro is discouraged.\n *\n * It is not safe to update or finalize a hash context again, if it has already\n * been finalized.\n *\n * @param[in,out] ctx Hash context\n * @param[out]    dst Where the final hash value will be stored\n *\n * @see av_hash_final_bin() provides an alternative API\n */\nvoid av_hash_final(struct AVHashContext *ctx, uint8_t *dst);\n\n/**\n * Finalize a hash context and store the actual hash value in a buffer.\n *\n * It is not safe to update or finalize a hash context again, if it has already\n * been finalized.\n *\n * If `size` is smaller than the hash size (given by av_hash_get_size()), the\n * hash is truncated; if size is larger, the buffer is padded with 0.\n *\n * @param[in,out] ctx  Hash context\n * @param[out]    dst  Where the final hash value will be stored\n * @param[in]     size Number of bytes to write to `dst`\n */\nvoid av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size);\n\n/**\n * Finalize a hash context and store the hexadecimal representation of the\n * actual hash value as a string.\n *\n * It is not safe to update or finalize a hash context again, if it has already\n * been finalized.\n *\n * The string is always 0-terminated.\n *\n * If `size` is smaller than `2 * hash_size + 1`, where `hash_size` is the\n * value returned by av_hash_get_size(), the string will be truncated.\n *\n * @param[in,out] ctx  Hash context\n * @param[out]    dst  Where the string will be stored\n * @param[in]     size Maximum number of bytes to write to `dst`\n */\nvoid av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size);\n\n/**\n * Finalize a hash context and store the Base64 representation of the\n * actual hash value as a string.\n *\n * It is not safe to update or finalize a hash context again, if it has already\n * been finalized.\n *\n * The string is always 0-terminated.\n *\n * If `size` is smaller than AV_BASE64_SIZE(hash_size), where `hash_size` is\n * the value returned by av_hash_get_size(), the string will be truncated.\n *\n * @param[in,out] ctx  Hash context\n * @param[out]    dst  Where the final hash value will be stored\n * @param[in]     size Maximum number of bytes to write to `dst`\n */\nvoid av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size);\n\n/**\n * Free hash context and set hash context pointer to `NULL`.\n *\n * @param[in,out] ctx  Pointer to hash context\n */\nvoid av_hash_freep(struct AVHashContext **ctx);\n\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_HASH_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hdr_dynamic_metadata.h",
    "content": "/*\n * Copyright (c) 2018 Mohammad Izadi <moh.izadi at gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HDR_DYNAMIC_METADATA_H\n#define AVUTIL_HDR_DYNAMIC_METADATA_H\n\n#include \"frame.h\"\n#include \"rational.h\"\n\n/**\n * Option for overlapping elliptical pixel selectors in an image.\n */\nenum AVHDRPlusOverlapProcessOption {\n    AV_HDR_PLUS_OVERLAP_PROCESS_WEIGHTED_AVERAGING = 0,\n    AV_HDR_PLUS_OVERLAP_PROCESS_LAYERING = 1,\n};\n\n/**\n * Represents the percentile at a specific percentage in\n * a distribution.\n */\ntypedef struct AVHDRPlusPercentile {\n    /**\n     * The percentage value corresponding to a specific percentile linearized\n     * RGB value in the processing window in the scene. The value shall be in\n     * the range of 0 to100, inclusive.\n     */\n    uint8_t percentage;\n\n    /**\n     * The linearized maxRGB value at a specific percentile in the processing\n     * window in the scene. The value shall be in the range of 0 to 1, inclusive\n     * and in multiples of 0.00001.\n     */\n    AVRational percentile;\n} AVHDRPlusPercentile;\n\n/**\n * Color transform parameters at a processing window in a dynamic metadata for\n * SMPTE 2094-40.\n */\ntypedef struct AVHDRPlusColorTransformParams {\n    /**\n     * The relative x coordinate of the top left pixel of the processing\n     * window. The value shall be in the range of 0 and 1, inclusive and\n     * in multiples of 1/(width of Picture - 1). The value 1 corresponds\n     * to the absolute coordinate of width of Picture - 1. The value for\n     * first processing window shall be 0.\n     */\n    AVRational window_upper_left_corner_x;\n\n    /**\n     * The relative y coordinate of the top left pixel of the processing\n     * window. The value shall be in the range of 0 and 1, inclusive and\n     * in multiples of 1/(height of Picture - 1). The value 1 corresponds\n     * to the absolute coordinate of height of Picture - 1. The value for\n     * first processing window shall be 0.\n     */\n    AVRational window_upper_left_corner_y;\n\n    /**\n     * The relative x coordinate of the bottom right pixel of the processing\n     * window. The value shall be in the range of 0 and 1, inclusive and\n     * in multiples of 1/(width of Picture - 1). The value 1 corresponds\n     * to the absolute coordinate of width of Picture - 1. The value for\n     * first processing window shall be 1.\n     */\n    AVRational window_lower_right_corner_x;\n\n    /**\n     * The relative y coordinate of the bottom right pixel of the processing\n     * window. The value shall be in the range of 0 and 1, inclusive and\n     * in multiples of 1/(height of Picture - 1). The value 1 corresponds\n     * to the absolute coordinate of height of Picture - 1. The value for\n     * first processing window shall be 1.\n     */\n    AVRational window_lower_right_corner_y;\n\n    /**\n     * The x coordinate of the center position of the concentric internal and\n     * external ellipses of the elliptical pixel selector in the processing\n     * window. The value shall be in the range of 0 to (width of Picture - 1),\n     * inclusive and in multiples of 1 pixel.\n     */\n    uint16_t center_of_ellipse_x;\n\n    /**\n     * The y coordinate of the center position of the concentric internal and\n     * external ellipses of the elliptical pixel selector in the processing\n     * window. The value shall be in the range of 0 to (height of Picture - 1),\n     * inclusive and in multiples of 1 pixel.\n     */\n    uint16_t center_of_ellipse_y;\n\n    /**\n     * The clockwise rotation angle in degree of arc with respect to the\n     * positive direction of the x-axis of the concentric internal and external\n     * ellipses of the elliptical pixel selector in the processing window. The\n     * value shall be in the range of 0 to 180, inclusive and in multiples of 1.\n     */\n    uint8_t rotation_angle;\n\n    /**\n     * The semi-major axis value of the internal ellipse of the elliptical pixel\n     * selector in amount of pixels in the processing window. The value shall be\n     * in the range of 1 to 65535, inclusive and in multiples of 1 pixel.\n     */\n    uint16_t semimajor_axis_internal_ellipse;\n\n    /**\n     * The semi-major axis value of the external ellipse of the elliptical pixel\n     * selector in amount of pixels in the processing window. The value\n     * shall not be less than semimajor_axis_internal_ellipse of the current\n     * processing window. The value shall be in the range of 1 to 65535,\n     * inclusive and in multiples of 1 pixel.\n     */\n    uint16_t semimajor_axis_external_ellipse;\n\n    /**\n     * The semi-minor axis value of the external ellipse of the elliptical pixel\n     * selector in amount of pixels in the processing window. The value shall be\n     * in the range of 1 to 65535, inclusive and in multiples of 1 pixel.\n     */\n    uint16_t semiminor_axis_external_ellipse;\n\n    /**\n     * Overlap process option indicates one of the two methods of combining\n     * rendered pixels in the processing window in an image with at least one\n     * elliptical pixel selector. For overlapping elliptical pixel selectors\n     * in an image, overlap_process_option shall have the same value.\n     */\n    enum AVHDRPlusOverlapProcessOption overlap_process_option;\n\n    /**\n     * The maximum of the color components of linearized RGB values in the\n     * processing window in the scene. The values should be in the range of 0 to\n     * 1, inclusive and in multiples of 0.00001. maxscl[ 0 ], maxscl[ 1 ], and\n     * maxscl[ 2 ] are corresponding to R, G, B color components respectively.\n     */\n    AVRational maxscl[3];\n\n    /**\n     * The average of linearized maxRGB values in the processing window in the\n     * scene. The value should be in the range of 0 to 1, inclusive and in\n     * multiples of 0.00001.\n     */\n    AVRational average_maxrgb;\n\n    /**\n     * The number of linearized maxRGB values at given percentiles in the\n     * processing window in the scene. The maximum value shall be 15.\n     */\n    uint8_t num_distribution_maxrgb_percentiles;\n\n    /**\n     * The linearized maxRGB values at given percentiles in the\n     * processing window in the scene.\n     */\n    AVHDRPlusPercentile distribution_maxrgb[15];\n\n    /**\n     * The fraction of selected pixels in the image that contains the brightest\n     * pixel in the scene. The value shall be in the range of 0 to 1, inclusive\n     * and in multiples of 0.001.\n     */\n    AVRational fraction_bright_pixels;\n\n    /**\n     * This flag indicates that the metadata for the tone mapping function in\n     * the processing window is present (for value of 1).\n     */\n    uint8_t tone_mapping_flag;\n\n    /**\n     * The x coordinate of the separation point between the linear part and the\n     * curved part of the tone mapping function. The value shall be in the range\n     * of 0 to 1, excluding 0 and in multiples of 1/4095.\n     */\n    AVRational knee_point_x;\n\n    /**\n     * The y coordinate of the separation point between the linear part and the\n     * curved part of the tone mapping function. The value shall be in the range\n     * of 0 to 1, excluding 0 and in multiples of 1/4095.\n     */\n    AVRational knee_point_y;\n\n    /**\n     * The number of the intermediate anchor parameters of the tone mapping\n     * function in the processing window. The maximum value shall be 15.\n     */\n    uint8_t num_bezier_curve_anchors;\n\n    /**\n     * The intermediate anchor parameters of the tone mapping function in the\n     * processing window in the scene. The values should be in the range of 0\n     * to 1, inclusive and in multiples of 1/1023.\n     */\n    AVRational bezier_curve_anchors[15];\n\n    /**\n     * This flag shall be equal to 0 in bitstreams conforming to this version of\n     * this Specification. Other values are reserved for future use.\n     */\n    uint8_t color_saturation_mapping_flag;\n\n    /**\n     * The color saturation gain in the processing window in the scene. The\n     * value shall be in the range of 0 to 63/8, inclusive and in multiples of\n     * 1/8. The default value shall be 1.\n     */\n    AVRational color_saturation_weight;\n} AVHDRPlusColorTransformParams;\n\n/**\n * This struct represents dynamic metadata for color volume transform -\n * application 4 of SMPTE 2094-40:2016 standard.\n *\n * To be used as payload of a AVFrameSideData or AVPacketSideData with the\n * appropriate type.\n *\n * @note The struct should be allocated with\n * av_dynamic_hdr_plus_alloc() and its size is not a part of\n * the public ABI.\n */\ntypedef struct AVDynamicHDRPlus {\n    /**\n     * Country code by Rec. ITU-T T.35 Annex A. The value shall be 0xB5.\n     */\n    uint8_t itu_t_t35_country_code;\n\n    /**\n     * Application version in the application defining document in ST-2094\n     * suite. The value shall be set to 0.\n     */\n    uint8_t application_version;\n\n    /**\n     * The number of processing windows. The value shall be in the range\n     * of 1 to 3, inclusive.\n     */\n    uint8_t num_windows;\n\n    /**\n     * The color transform parameters for every processing window.\n     */\n    AVHDRPlusColorTransformParams params[3];\n\n    /**\n     * The nominal maximum display luminance of the targeted system display,\n     * in units of 0.0001 candelas per square metre. The value shall be in\n     * the range of 0 to 10000, inclusive.\n     */\n    AVRational targeted_system_display_maximum_luminance;\n\n    /**\n     * This flag shall be equal to 0 in bit streams conforming to this version\n     * of this Specification. The value 1 is reserved for future use.\n     */\n    uint8_t targeted_system_display_actual_peak_luminance_flag;\n\n    /**\n     * The number of rows in the targeted system_display_actual_peak_luminance\n     * array. The value shall be in the range of 2 to 25, inclusive.\n     */\n    uint8_t num_rows_targeted_system_display_actual_peak_luminance;\n\n    /**\n     * The number of columns in the\n     * targeted_system_display_actual_peak_luminance array. The value shall be\n     * in the range of 2 to 25, inclusive.\n     */\n    uint8_t num_cols_targeted_system_display_actual_peak_luminance;\n\n    /**\n     * The normalized actual peak luminance of the targeted system display. The\n     * values should be in the range of 0 to 1, inclusive and in multiples of\n     * 1/15.\n     */\n    AVRational targeted_system_display_actual_peak_luminance[25][25];\n\n    /**\n     * This flag shall be equal to 0 in bitstreams conforming to this version of\n     * this Specification. The value 1 is reserved for future use.\n     */\n    uint8_t mastering_display_actual_peak_luminance_flag;\n\n    /**\n     * The number of rows in the mastering_display_actual_peak_luminance array.\n     * The value shall be in the range of 2 to 25, inclusive.\n     */\n    uint8_t num_rows_mastering_display_actual_peak_luminance;\n\n    /**\n     * The number of columns in the mastering_display_actual_peak_luminance\n     * array. The value shall be in the range of 2 to 25, inclusive.\n     */\n    uint8_t num_cols_mastering_display_actual_peak_luminance;\n\n    /**\n     * The normalized actual peak luminance of the mastering display used for\n     * mastering the image essence. The values should be in the range of 0 to 1,\n     * inclusive and in multiples of 1/15.\n     */\n    AVRational mastering_display_actual_peak_luminance[25][25];\n} AVDynamicHDRPlus;\n\n/**\n * Allocate an AVDynamicHDRPlus structure and set its fields to\n * default values. The resulting struct can be freed using av_freep().\n *\n * @return An AVDynamicHDRPlus filled with default values or NULL\n *         on failure.\n */\nAVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t *size);\n\n/**\n * Allocate a complete AVDynamicHDRPlus and add it to the frame.\n * @param frame The frame which side data is added to.\n *\n * @return The AVDynamicHDRPlus structure to be filled by caller or NULL\n *         on failure.\n */\nAVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);\n\n#endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hdr_dynamic_vivid_metadata.h",
    "content": "/*\n * Copyright (c) 2021 Limin Wang <lance.lmwang at gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HDR_DYNAMIC_VIVID_METADATA_H\n#define AVUTIL_HDR_DYNAMIC_VIVID_METADATA_H\n\n#include \"frame.h\"\n#include \"rational.h\"\n\n/**\n * Color tone mapping parameters at a processing window in a dynamic metadata for\n * CUVA 005.1:2021.\n */\ntypedef struct AVHDRVividColorToneMappingParams {\n    /**\n     * The nominal maximum display luminance of the targeted system display,\n     * in multiples of 1.0/4095 candelas per square metre. The value shall be in\n     * the range of 0.0 to 1.0, inclusive.\n     */\n    AVRational targeted_system_display_maximum_luminance;\n\n    /**\n     * This flag indicates that transfer the base paramter(for value of 1)\n     */\n    int base_enable_flag;\n\n    /**\n     * base_param_m_p in the base parameter,\n     * in multiples of 1.0/16383. The value shall be in\n     * the range of 0.0 to 1.0, inclusive.\n     */\n    AVRational base_param_m_p;\n\n    /**\n     * base_param_m_m in the base parameter,\n     * in multiples of 1.0/10. The value shall be in\n     * the range of 0.0 to 6.3, inclusive.\n     */\n    AVRational base_param_m_m;\n\n    /**\n     * base_param_m_a in the base parameter,\n     * in multiples of 1.0/1023. The value shall be in\n     * the range of 0.0 to 1.0 inclusive.\n     */\n    AVRational base_param_m_a;\n\n    /**\n     * base_param_m_b in the base parameter,\n     * in multiples of 1/1023. The value shall be in\n     * the range of 0.0 to 1.0, inclusive.\n     */\n    AVRational base_param_m_b;\n\n    /**\n     * base_param_m_n in the base parameter,\n     * in multiples of 1.0/10. The value shall be in\n     * the range of 0.0 to 6.3, inclusive.\n     */\n    AVRational base_param_m_n;\n\n    /**\n     * indicates k1_0 in the base parameter,\n     * base_param_k1 <= 1: k1_0 = base_param_k1\n     * base_param_k1 > 1: reserved\n     */\n    int base_param_k1;\n\n    /**\n     * indicates k2_0 in the base parameter,\n     * base_param_k2 <= 1: k2_0 = base_param_k2\n     * base_param_k2 > 1: reserved\n     */\n    int base_param_k2;\n\n    /**\n     * indicates k3_0 in the base parameter,\n     * base_param_k3 == 1: k3_0 = base_param_k3\n     * base_param_k3 == 2: k3_0 = maximum_maxrgb\n     * base_param_k3 > 2: reserved\n     */\n    int base_param_k3;\n\n    /**\n     * This flag indicates that delta mode of base paramter(for value of 1)\n     */\n    int base_param_Delta_enable_mode;\n\n    /**\n     * base_param_Delta in the base parameter,\n     * in multiples of 1.0/127. The value shall be in\n     * the range of 0.0 to 1.0, inclusive.\n     */\n    AVRational base_param_Delta;\n\n    /**\n     * indicates 3Spline_enable_flag in the base parameter,\n     * This flag indicates that transfer three Spline of base paramter(for value of 1)\n     */\n    int three_Spline_enable_flag;\n\n    /**\n     * The number of three Spline. The value shall be in the range\n     * of 1 to 2, inclusive.\n     */\n    int three_Spline_num;\n\n    /**\n     * The mode of three Spline. the value shall be in the range\n     * of 0 to 3, inclusive.\n     */\n    int three_Spline_TH_mode;\n\n    /**\n     * three_Spline_TH_enable_MB is in the range of 0.0 to 1.0, inclusive\n     * and in multiples of 1.0/255.\n     *\n     */\n    AVRational three_Spline_TH_enable_MB;\n\n    /**\n     * 3Spline_TH_enable of three Spline.\n     * The value shall be in the range of 0.0 to 1.0, inclusive.\n     * and in multiples of 1.0/4095.\n     */\n    AVRational three_Spline_TH_enable;\n\n    /**\n     * 3Spline_TH_Delta1 of three Spline.\n     * The value shall be in the range of 0.0 to 0.25, inclusive,\n     * and in multiples of 0.25/1023.\n     */\n    AVRational three_Spline_TH_Delta1;\n\n    /**\n     * 3Spline_TH_Delta2 of three Spline.\n     * The value shall be in the range of 0.0 to 0.25, inclusive,\n     * and in multiples of 0.25/1023.\n     */\n    AVRational three_Spline_TH_Delta2;\n\n    /**\n     * 3Spline_enable_Strength of three Spline.\n     * The value shall be in the range of 0.0 to 1.0, inclusive,\n     * and in multiples of 1.0/255.\n     */\n    AVRational three_Spline_enable_Strength;\n} AVHDRVividColorToneMappingParams;\n\n\n/**\n * Color transform parameters at a processing window in a dynamic metadata for\n * CUVA 005.1:2021.\n */\ntypedef struct AVHDRVividColorTransformParams {\n    /**\n     * Indicates the minimum brightness of the displayed content.\n     * The values should be in the range of 0.0 to 1.0,\n     * inclusive and in multiples of 1/4095.\n     */\n    AVRational minimum_maxrgb;\n\n    /**\n     * Indicates the average brightness of the displayed content.\n     * The values should be in the range of 0.0 to 1.0,\n     * inclusive and in multiples of 1/4095.\n     */\n    AVRational average_maxrgb;\n\n    /**\n     * Indicates the variance brightness of the displayed content.\n     * The values should be in the range of 0.0 to 1.0,\n     * inclusive and in multiples of 1/4095.\n     */\n    AVRational variance_maxrgb;\n\n    /**\n     * Indicates the maximum brightness of the displayed content.\n     * The values should be in the range of 0.0 to 1.0, inclusive\n     * and in multiples of 1/4095.\n     */\n    AVRational maximum_maxrgb;\n\n    /**\n     * This flag indicates that the metadata for the tone mapping function in\n     * the processing window is present (for value of 1).\n     */\n    int tone_mapping_mode_flag;\n\n    /**\n     * The number of tone mapping param. The value shall be in the range\n     * of 1 to 2, inclusive.\n     */\n    int tone_mapping_param_num;\n\n    /**\n     * The color tone mapping parameters.\n     */\n    AVHDRVividColorToneMappingParams tm_params[2];\n\n    /**\n     * This flag indicates that the metadata for the color saturation mapping in\n     * the processing window is present (for value of 1).\n     */\n    int color_saturation_mapping_flag;\n\n    /**\n     * The number of color saturation param. The value shall be in the range\n     * of 0 to 7, inclusive.\n     */\n    int color_saturation_num;\n\n    /**\n     * Indicates the color correction strength parameter.\n     * The values should be in the range of 0.0 to 2.0, inclusive\n     * and in multiples of 1/128.\n     */\n    AVRational color_saturation_gain[8];\n} AVHDRVividColorTransformParams;\n\n/**\n * This struct represents dynamic metadata for color volume transform -\n * CUVA 005.1:2021 standard\n *\n * To be used as payload of a AVFrameSideData or AVPacketSideData with the\n * appropriate type.\n *\n * @note The struct should be allocated with\n * av_dynamic_hdr_vivid_alloc() and its size is not a part of\n * the public ABI.\n */\ntypedef struct AVDynamicHDRVivid {\n    /**\n     * The system start code. The value shall be set to 0x01.\n     */\n    uint8_t system_start_code;\n\n    /**\n     * The number of processing windows. The value shall be set to 0x01\n     * if the system_start_code is 0x01.\n     */\n    uint8_t num_windows;\n\n    /**\n     * The color transform parameters for every processing window.\n     */\n    AVHDRVividColorTransformParams params[3];\n} AVDynamicHDRVivid;\n\n/**\n * Allocate an AVDynamicHDRVivid structure and set its fields to\n * default values. The resulting struct can be freed using av_freep().\n *\n * @return An AVDynamicHDRVivid filled with default values or NULL\n *         on failure.\n */\nAVDynamicHDRVivid *av_dynamic_hdr_vivid_alloc(size_t *size);\n\n/**\n * Allocate a complete AVDynamicHDRVivid and add it to the frame.\n * @param frame The frame which side data is added to.\n *\n * @return The AVDynamicHDRVivid structure to be filled by caller or NULL\n *         on failure.\n */\nAVDynamicHDRVivid *av_dynamic_hdr_vivid_create_side_data(AVFrame *frame);\n\n#endif /* AVUTIL_HDR_DYNAMIC_VIVID_METADATA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hmac.h",
    "content": "/*\n * Copyright (C) 2012 Martin Storsjo\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HMAC_H\n#define AVUTIL_HMAC_H\n\n#include <stdint.h>\n\n/**\n * @defgroup lavu_hmac HMAC\n * @ingroup lavu_crypto\n * @{\n */\n\nenum AVHMACType {\n    AV_HMAC_MD5,\n    AV_HMAC_SHA1,\n    AV_HMAC_SHA224,\n    AV_HMAC_SHA256,\n    AV_HMAC_SHA384,\n    AV_HMAC_SHA512,\n};\n\ntypedef struct AVHMAC AVHMAC;\n\n/**\n * Allocate an AVHMAC context.\n * @param type The hash function used for the HMAC.\n */\nAVHMAC *av_hmac_alloc(enum AVHMACType type);\n\n/**\n * Free an AVHMAC context.\n * @param ctx The context to free, may be NULL\n */\nvoid av_hmac_free(AVHMAC *ctx);\n\n/**\n * Initialize an AVHMAC context with an authentication key.\n * @param ctx    The HMAC context\n * @param key    The authentication key\n * @param keylen The length of the key, in bytes\n */\nvoid av_hmac_init(AVHMAC *ctx, const uint8_t *key, unsigned int keylen);\n\n/**\n * Hash data with the HMAC.\n * @param ctx  The HMAC context\n * @param data The data to hash\n * @param len  The length of the data, in bytes\n */\nvoid av_hmac_update(AVHMAC *ctx, const uint8_t *data, unsigned int len);\n\n/**\n * Finish hashing and output the HMAC digest.\n * @param ctx    The HMAC context\n * @param out    The output buffer to write the digest into\n * @param outlen The length of the out buffer, in bytes\n * @return       The number of bytes written to out, or a negative error code.\n */\nint av_hmac_final(AVHMAC *ctx, uint8_t *out, unsigned int outlen);\n\n/**\n * Hash an array of data with a key.\n * @param ctx    The HMAC context\n * @param data   The data to hash\n * @param len    The length of the data, in bytes\n * @param key    The authentication key\n * @param keylen The length of the key, in bytes\n * @param out    The output buffer to write the digest into\n * @param outlen The length of the out buffer, in bytes\n * @return       The number of bytes written to out, or a negative error code.\n */\nint av_hmac_calc(AVHMAC *ctx, const uint8_t *data, unsigned int len,\n                 const uint8_t *key, unsigned int keylen,\n                 uint8_t *out, unsigned int outlen);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_HMAC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_H\n#define AVUTIL_HWCONTEXT_H\n\n#include \"buffer.h\"\n#include \"frame.h\"\n#include \"log.h\"\n#include \"pixfmt.h\"\n\nenum AVHWDeviceType {\n    AV_HWDEVICE_TYPE_NONE,\n    AV_HWDEVICE_TYPE_VDPAU,\n    AV_HWDEVICE_TYPE_CUDA,\n    AV_HWDEVICE_TYPE_VAAPI,\n    AV_HWDEVICE_TYPE_DXVA2,\n    AV_HWDEVICE_TYPE_QSV,\n    AV_HWDEVICE_TYPE_VIDEOTOOLBOX,\n    AV_HWDEVICE_TYPE_D3D11VA,\n    AV_HWDEVICE_TYPE_DRM,\n    AV_HWDEVICE_TYPE_OPENCL,\n    AV_HWDEVICE_TYPE_MEDIACODEC,\n    AV_HWDEVICE_TYPE_VULKAN,\n};\n\ntypedef struct AVHWDeviceInternal AVHWDeviceInternal;\n\n/**\n * This struct aggregates all the (hardware/vendor-specific) \"high-level\" state,\n * i.e. state that is not tied to a concrete processing configuration.\n * E.g., in an API that supports hardware-accelerated encoding and decoding,\n * this struct will (if possible) wrap the state that is common to both encoding\n * and decoding and from which specific instances of encoders or decoders can be\n * derived.\n *\n * This struct is reference-counted with the AVBuffer mechanism. The\n * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field\n * points to the actual AVHWDeviceContext. Further objects derived from\n * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with\n * specific properties) will hold an internal reference to it. After all the\n * references are released, the AVHWDeviceContext itself will be freed,\n * optionally invoking a user-specified callback for uninitializing the hardware\n * state.\n */\ntypedef struct AVHWDeviceContext {\n    /**\n     * A class for logging. Set by av_hwdevice_ctx_alloc().\n     */\n    const AVClass *av_class;\n\n    /**\n     * Private data used internally by libavutil. Must not be accessed in any\n     * way by the caller.\n     */\n    AVHWDeviceInternal *internal;\n\n    /**\n     * This field identifies the underlying API used for hardware access.\n     *\n     * This field is set when this struct is allocated and never changed\n     * afterwards.\n     */\n    enum AVHWDeviceType type;\n\n    /**\n     * The format-specific data, allocated and freed by libavutil along with\n     * this context.\n     *\n     * Should be cast by the user to the format-specific context defined in the\n     * corresponding header (hwcontext_*.h) and filled as described in the\n     * documentation before calling av_hwdevice_ctx_init().\n     *\n     * After calling av_hwdevice_ctx_init() this struct should not be modified\n     * by the caller.\n     */\n    void *hwctx;\n\n    /**\n     * This field may be set by the caller before calling av_hwdevice_ctx_init().\n     *\n     * If non-NULL, this callback will be called when the last reference to\n     * this context is unreferenced, immediately before it is freed.\n     *\n     * @note when other objects (e.g an AVHWFramesContext) are derived from this\n     *       struct, this callback will be invoked after all such child objects\n     *       are fully uninitialized and their respective destructors invoked.\n     */\n    void (*free)(struct AVHWDeviceContext *ctx);\n\n    /**\n     * Arbitrary user data, to be used e.g. by the free() callback.\n     */\n    void *user_opaque;\n} AVHWDeviceContext;\n\ntypedef struct AVHWFramesInternal AVHWFramesInternal;\n\n/**\n * This struct describes a set or pool of \"hardware\" frames (i.e. those with\n * data not located in normal system memory). All the frames in the pool are\n * assumed to be allocated in the same way and interchangeable.\n *\n * This struct is reference-counted with the AVBuffer mechanism and tied to a\n * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor\n * yields a reference, whose data field points to the actual AVHWFramesContext\n * struct.\n */\ntypedef struct AVHWFramesContext {\n    /**\n     * A class for logging.\n     */\n    const AVClass *av_class;\n\n    /**\n     * Private data used internally by libavutil. Must not be accessed in any\n     * way by the caller.\n     */\n    AVHWFramesInternal *internal;\n\n    /**\n     * A reference to the parent AVHWDeviceContext. This reference is owned and\n     * managed by the enclosing AVHWFramesContext, but the caller may derive\n     * additional references from it.\n     */\n    AVBufferRef *device_ref;\n\n    /**\n     * The parent AVHWDeviceContext. This is simply a pointer to\n     * device_ref->data provided for convenience.\n     *\n     * Set by libavutil in av_hwframe_ctx_init().\n     */\n    AVHWDeviceContext *device_ctx;\n\n    /**\n     * The format-specific data, allocated and freed automatically along with\n     * this context.\n     *\n     * Should be cast by the user to the format-specific context defined in the\n     * corresponding header (hwframe_*.h) and filled as described in the\n     * documentation before calling av_hwframe_ctx_init().\n     *\n     * After any frames using this context are created, the contents of this\n     * struct should not be modified by the caller.\n     */\n    void *hwctx;\n\n    /**\n     * This field may be set by the caller before calling av_hwframe_ctx_init().\n     *\n     * If non-NULL, this callback will be called when the last reference to\n     * this context is unreferenced, immediately before it is freed.\n     */\n    void (*free)(struct AVHWFramesContext *ctx);\n\n    /**\n     * Arbitrary user data, to be used e.g. by the free() callback.\n     */\n    void *user_opaque;\n\n    /**\n     * A pool from which the frames are allocated by av_hwframe_get_buffer().\n     * This field may be set by the caller before calling av_hwframe_ctx_init().\n     * The buffers returned by calling av_buffer_pool_get() on this pool must\n     * have the properties described in the documentation in the corresponding hw\n     * type's header (hwcontext_*.h). The pool will be freed strictly before\n     * this struct's free() callback is invoked.\n     *\n     * This field may be NULL, then libavutil will attempt to allocate a pool\n     * internally. Note that certain device types enforce pools allocated at\n     * fixed size (frame count), which cannot be extended dynamically. In such a\n     * case, initial_pool_size must be set appropriately.\n     */\n    AVBufferPool *pool;\n\n    /**\n     * Initial size of the frame pool. If a device type does not support\n     * dynamically resizing the pool, then this is also the maximum pool size.\n     *\n     * May be set by the caller before calling av_hwframe_ctx_init(). Must be\n     * set if pool is NULL and the device type does not support dynamic pools.\n     */\n    int initial_pool_size;\n\n    /**\n     * The pixel format identifying the underlying HW surface type.\n     *\n     * Must be a hwaccel format, i.e. the corresponding descriptor must have the\n     * AV_PIX_FMT_FLAG_HWACCEL flag set.\n     *\n     * Must be set by the user before calling av_hwframe_ctx_init().\n     */\n    enum AVPixelFormat format;\n\n    /**\n     * The pixel format identifying the actual data layout of the hardware\n     * frames.\n     *\n     * Must be set by the caller before calling av_hwframe_ctx_init().\n     *\n     * @note when the underlying API does not provide the exact data layout, but\n     * only the colorspace/bit depth, this field should be set to the fully\n     * planar version of that format (e.g. for 8-bit 420 YUV it should be\n     * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else).\n     */\n    enum AVPixelFormat sw_format;\n\n    /**\n     * The allocated dimensions of the frames in this pool.\n     *\n     * Must be set by the user before calling av_hwframe_ctx_init().\n     */\n    int width, height;\n} AVHWFramesContext;\n\n/**\n * Look up an AVHWDeviceType by name.\n *\n * @param name String name of the device type (case-insensitive).\n * @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if\n *         not found.\n */\nenum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name);\n\n/** Get the string name of an AVHWDeviceType.\n *\n * @param type Type from enum AVHWDeviceType.\n * @return Pointer to a static string containing the name, or NULL if the type\n *         is not valid.\n */\nconst char *av_hwdevice_get_type_name(enum AVHWDeviceType type);\n\n/**\n * Iterate over supported device types.\n *\n * @param type AV_HWDEVICE_TYPE_NONE initially, then the previous type\n *             returned by this function in subsequent iterations.\n * @return The next usable device type from enum AVHWDeviceType, or\n *         AV_HWDEVICE_TYPE_NONE if there are no more.\n */\nenum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev);\n\n/**\n * Allocate an AVHWDeviceContext for a given hardware type.\n *\n * @param type the type of the hardware device to allocate.\n * @return a reference to the newly created AVHWDeviceContext on success or NULL\n *         on failure.\n */\nAVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type);\n\n/**\n * Finalize the device context before use. This function must be called after\n * the context is filled with all the required information and before it is\n * used in any way.\n *\n * @param ref a reference to the AVHWDeviceContext\n * @return 0 on success, a negative AVERROR code on failure\n */\nint av_hwdevice_ctx_init(AVBufferRef *ref);\n\n/**\n * Open a device of the specified type and create an AVHWDeviceContext for it.\n *\n * This is a convenience function intended to cover the simple cases. Callers\n * who need to fine-tune device creation/management should open the device\n * manually and then wrap it in an AVHWDeviceContext using\n * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init().\n *\n * The returned context is already initialized and ready for use, the caller\n * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of\n * the created AVHWDeviceContext are set by this function and should not be\n * touched by the caller.\n *\n * @param device_ctx On success, a reference to the newly-created device context\n *                   will be written here. The reference is owned by the caller\n *                   and must be released with av_buffer_unref() when no longer\n *                   needed. On failure, NULL will be written to this pointer.\n * @param type The type of the device to create.\n * @param device A type-specific string identifying the device to open.\n * @param opts A dictionary of additional (type-specific) options to use in\n *             opening the device. The dictionary remains owned by the caller.\n * @param flags currently unused\n *\n * @return 0 on success, a negative AVERROR code on failure.\n */\nint av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type,\n                           const char *device, AVDictionary *opts, int flags);\n\n/**\n * Create a new device of the specified type from an existing device.\n *\n * If the source device is a device of the target type or was originally\n * derived from such a device (possibly through one or more intermediate\n * devices of other types), then this will return a reference to the\n * existing device of the same type as is requested.\n *\n * Otherwise, it will attempt to derive a new device from the given source\n * device.  If direct derivation to the new type is not implemented, it will\n * attempt the same derivation from each ancestor of the source device in\n * turn looking for an implemented derivation method.\n *\n * @param dst_ctx On success, a reference to the newly-created\n *                AVHWDeviceContext.\n * @param type    The type of the new device to create.\n * @param src_ctx A reference to an existing AVHWDeviceContext which will be\n *                used to create the new device.\n * @param flags   Currently unused; should be set to zero.\n * @return        Zero on success, a negative AVERROR code on failure.\n */\nint av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx,\n                                   enum AVHWDeviceType type,\n                                   AVBufferRef *src_ctx, int flags);\n\n/**\n * Create a new device of the specified type from an existing device.\n *\n * This function performs the same action as av_hwdevice_ctx_create_derived,\n * however, it is able to set options for the new device to be derived.\n *\n * @param dst_ctx On success, a reference to the newly-created\n *                AVHWDeviceContext.\n * @param type    The type of the new device to create.\n * @param src_ctx A reference to an existing AVHWDeviceContext which will be\n *                used to create the new device.\n * @param options Options for the new device to create, same format as in\n *                av_hwdevice_ctx_create.\n * @param flags   Currently unused; should be set to zero.\n * @return        Zero on success, a negative AVERROR code on failure.\n */\nint av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ctx,\n                                        enum AVHWDeviceType type,\n                                        AVBufferRef *src_ctx,\n                                        AVDictionary *options, int flags);\n\n/**\n * Allocate an AVHWFramesContext tied to a given device context.\n *\n * @param device_ctx a reference to a AVHWDeviceContext. This function will make\n *                   a new reference for internal use, the one passed to the\n *                   function remains owned by the caller.\n * @return a reference to the newly created AVHWFramesContext on success or NULL\n *         on failure.\n */\nAVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx);\n\n/**\n * Finalize the context before use. This function must be called after the\n * context is filled with all the required information and before it is attached\n * to any frames.\n *\n * @param ref a reference to the AVHWFramesContext\n * @return 0 on success, a negative AVERROR code on failure\n */\nint av_hwframe_ctx_init(AVBufferRef *ref);\n\n/**\n * Allocate a new frame attached to the given AVHWFramesContext.\n *\n * @param hwframe_ctx a reference to an AVHWFramesContext\n * @param frame an empty (freshly allocated or unreffed) frame to be filled with\n *              newly allocated buffers.\n * @param flags currently unused, should be set to zero\n * @return 0 on success, a negative AVERROR code on failure\n */\nint av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags);\n\n/**\n * Copy data to or from a hw surface. At least one of dst/src must have an\n * AVHWFramesContext attached.\n *\n * If src has an AVHWFramesContext attached, then the format of dst (if set)\n * must use one of the formats returned by av_hwframe_transfer_get_formats(src,\n * AV_HWFRAME_TRANSFER_DIRECTION_FROM).\n * If dst has an AVHWFramesContext attached, then the format of src must use one\n * of the formats returned by av_hwframe_transfer_get_formats(dst,\n * AV_HWFRAME_TRANSFER_DIRECTION_TO)\n *\n * dst may be \"clean\" (i.e. with data/buf pointers unset), in which case the\n * data buffers will be allocated by this function using av_frame_get_buffer().\n * If dst->format is set, then this format will be used, otherwise (when\n * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen.\n *\n * The two frames must have matching allocated dimensions (i.e. equal to\n * AVHWFramesContext.width/height), since not all device types support\n * transferring a sub-rectangle of the whole surface. The display dimensions\n * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but\n * also have to be equal for both frames. When the display dimensions are\n * smaller than the allocated dimensions, the content of the padding in the\n * destination frame is unspecified.\n *\n * @param dst the destination frame. dst is not touched on failure.\n * @param src the source frame.\n * @param flags currently unused, should be set to zero\n * @return 0 on success, a negative AVERROR error code on failure.\n */\nint av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags);\n\nenum AVHWFrameTransferDirection {\n    /**\n     * Transfer the data from the queried hw frame.\n     */\n    AV_HWFRAME_TRANSFER_DIRECTION_FROM,\n\n    /**\n     * Transfer the data to the queried hw frame.\n     */\n    AV_HWFRAME_TRANSFER_DIRECTION_TO,\n};\n\n/**\n * Get a list of possible source or target formats usable in\n * av_hwframe_transfer_data().\n *\n * @param hwframe_ctx the frame context to obtain the information for\n * @param dir the direction of the transfer\n * @param formats the pointer to the output format list will be written here.\n *                The list is terminated with AV_PIX_FMT_NONE and must be freed\n *                by the caller when no longer needed using av_free().\n *                If this function returns successfully, the format list will\n *                have at least one item (not counting the terminator).\n *                On failure, the contents of this pointer are unspecified.\n * @param flags currently unused, should be set to zero\n * @return 0 on success, a negative AVERROR code on failure.\n */\nint av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx,\n                                    enum AVHWFrameTransferDirection dir,\n                                    enum AVPixelFormat **formats, int flags);\n\n\n/**\n * This struct describes the constraints on hardware frames attached to\n * a given device with a hardware-specific configuration.  This is returned\n * by av_hwdevice_get_hwframe_constraints() and must be freed by\n * av_hwframe_constraints_free() after use.\n */\ntypedef struct AVHWFramesConstraints {\n    /**\n     * A list of possible values for format in the hw_frames_ctx,\n     * terminated by AV_PIX_FMT_NONE.  This member will always be filled.\n     */\n    enum AVPixelFormat *valid_hw_formats;\n\n    /**\n     * A list of possible values for sw_format in the hw_frames_ctx,\n     * terminated by AV_PIX_FMT_NONE.  Can be NULL if this information is\n     * not known.\n     */\n    enum AVPixelFormat *valid_sw_formats;\n\n    /**\n     * The minimum size of frames in this hw_frames_ctx.\n     * (Zero if not known.)\n     */\n    int min_width;\n    int min_height;\n\n    /**\n     * The maximum size of frames in this hw_frames_ctx.\n     * (INT_MAX if not known / no limit.)\n     */\n    int max_width;\n    int max_height;\n} AVHWFramesConstraints;\n\n/**\n * Allocate a HW-specific configuration structure for a given HW device.\n * After use, the user must free all members as required by the specific\n * hardware structure being used, then free the structure itself with\n * av_free().\n *\n * @param device_ctx a reference to the associated AVHWDeviceContext.\n * @return The newly created HW-specific configuration structure on\n *         success or NULL on failure.\n */\nvoid *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx);\n\n/**\n * Get the constraints on HW frames given a device and the HW-specific\n * configuration to be used with that device.  If no HW-specific\n * configuration is provided, returns the maximum possible capabilities\n * of the device.\n *\n * @param ref a reference to the associated AVHWDeviceContext.\n * @param hwconfig a filled HW-specific configuration structure, or NULL\n *        to return the maximum possible capabilities of the device.\n * @return AVHWFramesConstraints structure describing the constraints\n *         on the device, or NULL if not available.\n */\nAVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,\n                                                           const void *hwconfig);\n\n/**\n * Free an AVHWFrameConstraints structure.\n *\n * @param constraints The (filled or unfilled) AVHWFrameConstraints structure.\n */\nvoid av_hwframe_constraints_free(AVHWFramesConstraints **constraints);\n\n\n/**\n * Flags to apply to frame mappings.\n */\nenum {\n    /**\n     * The mapping must be readable.\n     */\n    AV_HWFRAME_MAP_READ      = 1 << 0,\n    /**\n     * The mapping must be writeable.\n     */\n    AV_HWFRAME_MAP_WRITE     = 1 << 1,\n    /**\n     * The mapped frame will be overwritten completely in subsequent\n     * operations, so the current frame data need not be loaded.  Any values\n     * which are not overwritten are unspecified.\n     */\n    AV_HWFRAME_MAP_OVERWRITE = 1 << 2,\n    /**\n     * The mapping must be direct.  That is, there must not be any copying in\n     * the map or unmap steps.  Note that performance of direct mappings may\n     * be much lower than normal memory.\n     */\n    AV_HWFRAME_MAP_DIRECT    = 1 << 3,\n};\n\n/**\n * Map a hardware frame.\n *\n * This has a number of different possible effects, depending on the format\n * and origin of the src and dst frames.  On input, src should be a usable\n * frame with valid buffers and dst should be blank (typically as just created\n * by av_frame_alloc()).  src should have an associated hwframe context, and\n * dst may optionally have a format and associated hwframe context.\n *\n * If src was created by mapping a frame from the hwframe context of dst,\n * then this function undoes the mapping - dst is replaced by a reference to\n * the frame that src was originally mapped from.\n *\n * If both src and dst have an associated hwframe context, then this function\n * attempts to map the src frame from its hardware context to that of dst and\n * then fill dst with appropriate data to be usable there.  This will only be\n * possible if the hwframe contexts and associated devices are compatible -\n * given compatible devices, av_hwframe_ctx_create_derived() can be used to\n * create a hwframe context for dst in which mapping should be possible.\n *\n * If src has a hwframe context but dst does not, then the src frame is\n * mapped to normal memory and should thereafter be usable as a normal frame.\n * If the format is set on dst, then the mapping will attempt to create dst\n * with that format and fail if it is not possible.  If format is unset (is\n * AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate\n * format to use is (probably the sw_format of the src hwframe context).\n *\n * A return value of AVERROR(ENOSYS) indicates that the mapping is not\n * possible with the given arguments and hwframe setup, while other return\n * values indicate that it failed somehow.\n *\n * On failure, the destination frame will be left blank, except for the\n * hw_frames_ctx/format fields thay may have been set by the caller - those will\n * be preserved as they were.\n *\n * @param dst Destination frame, to contain the mapping.\n * @param src Source frame, to be mapped.\n * @param flags Some combination of AV_HWFRAME_MAP_* flags.\n * @return Zero on success, negative AVERROR code on failure.\n */\nint av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags);\n\n\n/**\n * Create and initialise an AVHWFramesContext as a mapping of another existing\n * AVHWFramesContext on a different device.\n *\n * av_hwframe_ctx_init() should not be called after this.\n *\n * @param derived_frame_ctx  On success, a reference to the newly created\n *                           AVHWFramesContext.\n * @param derived_device_ctx A reference to the device to create the new\n *                           AVHWFramesContext on.\n * @param source_frame_ctx   A reference to an existing AVHWFramesContext\n *                           which will be mapped to the derived context.\n * @param flags  Some combination of AV_HWFRAME_MAP_* flags, defining the\n *               mapping parameters to apply to frames which are allocated\n *               in the derived device.\n * @return       Zero on success, negative AVERROR code on failure.\n */\nint av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx,\n                                  enum AVPixelFormat format,\n                                  AVBufferRef *derived_device_ctx,\n                                  AVBufferRef *source_frame_ctx,\n                                  int flags);\n\n#endif /* AVUTIL_HWCONTEXT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_cuda.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n\n#ifndef AVUTIL_HWCONTEXT_CUDA_H\n#define AVUTIL_HWCONTEXT_CUDA_H\n\n#ifndef CUDA_VERSION\n#include <cuda.h>\n#endif\n\n#include \"pixfmt.h\"\n\n/**\n * @file\n * An API-specific header for AV_HWDEVICE_TYPE_CUDA.\n *\n * This API supports dynamic frame pools. AVHWFramesContext.pool must return\n * AVBufferRefs whose data pointer is a CUdeviceptr.\n */\n\ntypedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;\n\n/**\n * This struct is allocated as AVHWDeviceContext.hwctx\n */\ntypedef struct AVCUDADeviceContext {\n    CUcontext cuda_ctx;\n    CUstream stream;\n    AVCUDADeviceContextInternal *internal;\n} AVCUDADeviceContext;\n\n/**\n * AVHWFramesContext.hwctx is currently not used\n */\n\n/**\n * @defgroup hwcontext_cuda Device context creation flags\n *\n * Flags for av_hwdevice_ctx_create.\n *\n * @{\n */\n\n/**\n * Use primary device context instead of creating a new one.\n */\n#define AV_CUDA_USE_PRIMARY_CONTEXT (1 << 0)\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_HWCONTEXT_CUDA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_d3d11va.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_D3D11VA_H\n#define AVUTIL_HWCONTEXT_D3D11VA_H\n\n/**\n * @file\n * An API-specific header for AV_HWDEVICE_TYPE_D3D11VA.\n *\n * The default pool implementation will be fixed-size if initial_pool_size is\n * set (and allocate elements from an array texture). Otherwise it will allocate\n * individual textures. Be aware that decoding requires a single array texture.\n *\n * Using sw_format==AV_PIX_FMT_YUV420P has special semantics, and maps to\n * DXGI_FORMAT_420_OPAQUE. av_hwframe_transfer_data() is not supported for\n * this format. Refer to MSDN for details.\n *\n * av_hwdevice_ctx_create() for this device type supports a key named \"debug\"\n * for the AVDictionary entry. If this is set to any value, the device creation\n * code will try to load various supported D3D debugging layers.\n */\n\n#include <d3d11.h>\n#include <stdint.h>\n\n/**\n * This struct is allocated as AVHWDeviceContext.hwctx\n */\ntypedef struct AVD3D11VADeviceContext {\n    /**\n     * Device used for texture creation and access. This can also be used to\n     * set the libavcodec decoding device.\n     *\n     * Must be set by the user. This is the only mandatory field - the other\n     * device context fields are set from this and are available for convenience.\n     *\n     * Deallocating the AVHWDeviceContext will always release this interface,\n     * and it does not matter whether it was user-allocated.\n     */\n    ID3D11Device        *device;\n\n    /**\n     * If unset, this will be set from the device field on init.\n     *\n     * Deallocating the AVHWDeviceContext will always release this interface,\n     * and it does not matter whether it was user-allocated.\n     */\n    ID3D11DeviceContext *device_context;\n\n    /**\n     * If unset, this will be set from the device field on init.\n     *\n     * Deallocating the AVHWDeviceContext will always release this interface,\n     * and it does not matter whether it was user-allocated.\n     */\n    ID3D11VideoDevice   *video_device;\n\n    /**\n     * If unset, this will be set from the device_context field on init.\n     *\n     * Deallocating the AVHWDeviceContext will always release this interface,\n     * and it does not matter whether it was user-allocated.\n     */\n    ID3D11VideoContext  *video_context;\n\n    /**\n     * Callbacks for locking. They protect accesses to device_context and\n     * video_context calls. They also protect access to the internal staging\n     * texture (for av_hwframe_transfer_data() calls). They do NOT protect\n     * access to hwcontext or decoder state in general.\n     *\n     * If unset on init, the hwcontext implementation will set them to use an\n     * internal mutex.\n     *\n     * The underlying lock must be recursive. lock_ctx is for free use by the\n     * locking implementation.\n     */\n    void (*lock)(void *lock_ctx);\n    void (*unlock)(void *lock_ctx);\n    void *lock_ctx;\n} AVD3D11VADeviceContext;\n\n/**\n * D3D11 frame descriptor for pool allocation.\n *\n * In user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs\n * with the data pointer pointing at an object of this type describing the\n * planes of the frame.\n *\n * This has no use outside of custom allocation, and AVFrame AVBufferRef do not\n * necessarily point to an instance of this struct.\n */\ntypedef struct AVD3D11FrameDescriptor {\n    /**\n     * The texture in which the frame is located. The reference count is\n     * managed by the AVBufferRef, and destroying the reference will release\n     * the interface.\n     *\n     * Normally stored in AVFrame.data[0].\n     */\n    ID3D11Texture2D *texture;\n\n    /**\n     * The index into the array texture element representing the frame, or 0\n     * if the texture is not an array texture.\n     *\n     * Normally stored in AVFrame.data[1] (cast from intptr_t).\n     */\n    intptr_t index;\n} AVD3D11FrameDescriptor;\n\n/**\n * This struct is allocated as AVHWFramesContext.hwctx\n */\ntypedef struct AVD3D11VAFramesContext {\n    /**\n     * The canonical texture used for pool allocation. If this is set to NULL\n     * on init, the hwframes implementation will allocate and set an array\n     * texture if initial_pool_size > 0.\n     *\n     * The only situation when the API user should set this is:\n     * - the user wants to do manual pool allocation (setting\n     *   AVHWFramesContext.pool), instead of letting AVHWFramesContext\n     *   allocate the pool\n     * - of an array texture\n     * - and wants it to use it for decoding\n     * - this has to be done before calling av_hwframe_ctx_init()\n     *\n     * Deallocating the AVHWFramesContext will always release this interface,\n     * and it does not matter whether it was user-allocated.\n     *\n     * This is in particular used by the libavcodec D3D11VA hwaccel, which\n     * requires a single array texture. It will create ID3D11VideoDecoderOutputView\n     * objects for each array texture element on decoder initialization.\n     */\n    ID3D11Texture2D *texture;\n\n    /**\n     * D3D11_TEXTURE2D_DESC.BindFlags used for texture creation. The user must\n     * at least set D3D11_BIND_DECODER if the frames context is to be used for\n     * video decoding.\n     * This field is ignored/invalid if a user-allocated texture is provided.\n     */\n    UINT BindFlags;\n\n    /**\n     * D3D11_TEXTURE2D_DESC.MiscFlags used for texture creation.\n     * This field is ignored/invalid if a user-allocated texture is provided.\n     */\n    UINT MiscFlags;\n\n    /**\n     * In case if texture structure member above is not NULL contains the same texture\n     * pointer for all elements and different indexes into the array texture.\n     * In case if texture structure member above is NULL, all elements contains\n     * pointers to separate non-array textures and 0 indexes.\n     * This field is ignored/invalid if a user-allocated texture is provided.\n    */\n    AVD3D11FrameDescriptor *texture_infos;\n} AVD3D11VAFramesContext;\n\n#endif /* AVUTIL_HWCONTEXT_D3D11VA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_drm.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_DRM_H\n#define AVUTIL_HWCONTEXT_DRM_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * @file\n * API-specific header for AV_HWDEVICE_TYPE_DRM.\n *\n * Internal frame allocation is not currently supported - all frames\n * must be allocated by the user.  Thus AVHWFramesContext is always\n * NULL, though this may change if support for frame allocation is\n * added in future.\n */\n\nenum {\n    /**\n     * The maximum number of layers/planes in a DRM frame.\n     */\n    AV_DRM_MAX_PLANES = 4\n};\n\n/**\n * DRM object descriptor.\n *\n * Describes a single DRM object, addressing it as a PRIME file\n * descriptor.\n */\ntypedef struct AVDRMObjectDescriptor {\n    /**\n     * DRM PRIME fd for the object.\n     */\n    int fd;\n    /**\n     * Total size of the object.\n     *\n     * (This includes any parts not which do not contain image data.)\n     */\n    size_t size;\n    /**\n     * Format modifier applied to the object (DRM_FORMAT_MOD_*).\n     *\n     * If the format modifier is unknown then this should be set to\n     * DRM_FORMAT_MOD_INVALID.\n     */\n    uint64_t format_modifier;\n} AVDRMObjectDescriptor;\n\n/**\n * DRM plane descriptor.\n *\n * Describes a single plane of a layer, which is contained within\n * a single object.\n */\ntypedef struct AVDRMPlaneDescriptor {\n    /**\n     * Index of the object containing this plane in the objects\n     * array of the enclosing frame descriptor.\n     */\n    int object_index;\n    /**\n     * Offset within that object of this plane.\n     */\n    ptrdiff_t offset;\n    /**\n     * Pitch (linesize) of this plane.\n     */\n    ptrdiff_t pitch;\n} AVDRMPlaneDescriptor;\n\n/**\n * DRM layer descriptor.\n *\n * Describes a single layer within a frame.  This has the structure\n * defined by its format, and will contain one or more planes.\n */\ntypedef struct AVDRMLayerDescriptor {\n    /**\n     * Format of the layer (DRM_FORMAT_*).\n     */\n    uint32_t format;\n    /**\n     * Number of planes in the layer.\n     *\n     * This must match the number of planes required by format.\n     */\n    int nb_planes;\n    /**\n     * Array of planes in this layer.\n     */\n    AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES];\n} AVDRMLayerDescriptor;\n\n/**\n * DRM frame descriptor.\n *\n * This is used as the data pointer for AV_PIX_FMT_DRM_PRIME frames.\n * It is also used by user-allocated frame pools - allocating in\n * AVHWFramesContext.pool must return AVBufferRefs which contain\n * an object of this type.\n *\n * The fields of this structure should be set such it can be\n * imported directly by EGL using the EGL_EXT_image_dma_buf_import\n * and EGL_EXT_image_dma_buf_import_modifiers extensions.\n * (Note that the exact layout of a particular format may vary between\n * platforms - we only specify that the same platform should be able\n * to import it.)\n *\n * The total number of planes must not exceed AV_DRM_MAX_PLANES, and\n * the order of the planes by increasing layer index followed by\n * increasing plane index must be the same as the order which would\n * be used for the data pointers in the equivalent software format.\n */\ntypedef struct AVDRMFrameDescriptor {\n    /**\n     * Number of DRM objects making up this frame.\n     */\n    int nb_objects;\n    /**\n     * Array of objects making up the frame.\n     */\n    AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES];\n    /**\n     * Number of layers in the frame.\n     */\n    int nb_layers;\n    /**\n     * Array of layers in the frame.\n     */\n    AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES];\n} AVDRMFrameDescriptor;\n\n/**\n * DRM device.\n *\n * Allocated as AVHWDeviceContext.hwctx.\n */\ntypedef struct AVDRMDeviceContext {\n    /**\n     * File descriptor of DRM device.\n     *\n     * This is used as the device to create frames on, and may also be\n     * used in some derivation and mapping operations.\n     *\n     * If no device is required, set to -1.\n     */\n    int fd;\n} AVDRMDeviceContext;\n\n#endif /* AVUTIL_HWCONTEXT_DRM_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_dxva2.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n\n#ifndef AVUTIL_HWCONTEXT_DXVA2_H\n#define AVUTIL_HWCONTEXT_DXVA2_H\n\n/**\n * @file\n * An API-specific header for AV_HWDEVICE_TYPE_DXVA2.\n *\n * Only fixed-size pools are supported.\n *\n * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs\n * with the data pointer set to a pointer to IDirect3DSurface9.\n */\n\n#include <d3d9.h>\n#include <dxva2api.h>\n\n/**\n * This struct is allocated as AVHWDeviceContext.hwctx\n */\ntypedef struct AVDXVA2DeviceContext {\n    IDirect3DDeviceManager9 *devmgr;\n} AVDXVA2DeviceContext;\n\n/**\n * This struct is allocated as AVHWFramesContext.hwctx\n */\ntypedef struct AVDXVA2FramesContext {\n    /**\n     * The surface type (e.g. DXVA2_VideoProcessorRenderTarget or\n     * DXVA2_VideoDecoderRenderTarget). Must be set by the caller.\n     */\n    DWORD               surface_type;\n\n    /**\n     * The surface pool. When an external pool is not provided by the caller,\n     * this will be managed (allocated and filled on init, freed on uninit) by\n     * libavutil.\n     */\n    IDirect3DSurface9 **surfaces;\n    int              nb_surfaces;\n\n    /**\n     * Certain drivers require the decoder to be destroyed before the surfaces.\n     * To allow internally managed pools to work properly in such cases, this\n     * field is provided.\n     *\n     * If it is non-NULL, libavutil will call IDirectXVideoDecoder_Release() on\n     * it just before the internal surface pool is freed.\n     *\n     * This is for convenience only. Some code uses other methods to manage the\n     * decoder reference.\n     */\n    IDirectXVideoDecoder *decoder_to_release;\n} AVDXVA2FramesContext;\n\n#endif /* AVUTIL_HWCONTEXT_DXVA2_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_mediacodec.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_MEDIACODEC_H\n#define AVUTIL_HWCONTEXT_MEDIACODEC_H\n\n/**\n * MediaCodec details.\n *\n * Allocated as AVHWDeviceContext.hwctx\n */\ntypedef struct AVMediaCodecDeviceContext {\n    /**\n     * android/view/Surface handle, to be filled by the user.\n     *\n     * This is the default surface used by decoders on this device.\n     */\n    void *surface;\n} AVMediaCodecDeviceContext;\n\n#endif /* AVUTIL_HWCONTEXT_MEDIACODEC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_opencl.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_OPENCL_H\n#define AVUTIL_HWCONTEXT_OPENCL_H\n\n#ifdef __APPLE__\n#include <OpenCL/cl.h>\n#else\n#include <CL/cl.h>\n#endif\n\n#include \"frame.h\"\n\n/**\n * @file\n * API-specific header for AV_HWDEVICE_TYPE_OPENCL.\n *\n * Pools allocated internally are always dynamic, and are primarily intended\n * to be used in OpenCL-only cases.  If interoperation is required, it is\n * typically required to allocate frames in the other API and then map the\n * frames context to OpenCL with av_hwframe_ctx_create_derived().\n */\n\n/**\n * OpenCL frame descriptor for pool allocation.\n *\n * In user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs\n * with the data pointer pointing at an object of this type describing the\n * planes of the frame.\n */\ntypedef struct AVOpenCLFrameDescriptor {\n    /**\n     * Number of planes in the frame.\n     */\n    int nb_planes;\n    /**\n     * OpenCL image2d objects for each plane of the frame.\n     */\n    cl_mem planes[AV_NUM_DATA_POINTERS];\n} AVOpenCLFrameDescriptor;\n\n/**\n * OpenCL device details.\n *\n * Allocated as AVHWDeviceContext.hwctx\n */\ntypedef struct AVOpenCLDeviceContext {\n    /**\n     * The primary device ID of the device.  If multiple OpenCL devices\n     * are associated with the context then this is the one which will\n     * be used for all operations internal to FFmpeg.\n     */\n    cl_device_id device_id;\n    /**\n     * The OpenCL context which will contain all operations and frames on\n     * this device.\n     */\n    cl_context context;\n    /**\n     * The default command queue for this device, which will be used by all\n     * frames contexts which do not have their own command queue.  If not\n     * intialised by the user, a default queue will be created on the\n     * primary device.\n     */\n    cl_command_queue command_queue;\n} AVOpenCLDeviceContext;\n\n/**\n * OpenCL-specific data associated with a frame pool.\n *\n * Allocated as AVHWFramesContext.hwctx.\n */\ntypedef struct AVOpenCLFramesContext {\n    /**\n     * The command queue used for internal asynchronous operations on this\n     * device (av_hwframe_transfer_data(), av_hwframe_map()).\n     *\n     * If this is not set, the command queue from the associated device is\n     * used instead.\n     */\n    cl_command_queue command_queue;\n} AVOpenCLFramesContext;\n\n#endif /* AVUTIL_HWCONTEXT_OPENCL_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_qsv.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_QSV_H\n#define AVUTIL_HWCONTEXT_QSV_H\n\n#include <mfx/mfxvideo.h>\n\n/**\n * @file\n * An API-specific header for AV_HWDEVICE_TYPE_QSV.\n *\n * This API does not support dynamic frame pools. AVHWFramesContext.pool must\n * contain AVBufferRefs whose data pointer points to an mfxFrameSurface1 struct.\n */\n\n/**\n * This struct is allocated as AVHWDeviceContext.hwctx\n */\ntypedef struct AVQSVDeviceContext {\n    mfxSession session;\n} AVQSVDeviceContext;\n\n/**\n * This struct is allocated as AVHWFramesContext.hwctx\n */\ntypedef struct AVQSVFramesContext {\n    mfxFrameSurface1 *surfaces;\n    int            nb_surfaces;\n\n    /**\n     * A combination of MFX_MEMTYPE_* describing the frame pool.\n     */\n    int frame_type;\n} AVQSVFramesContext;\n\n#endif /* AVUTIL_HWCONTEXT_QSV_H */\n\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_vaapi.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_VAAPI_H\n#define AVUTIL_HWCONTEXT_VAAPI_H\n\n#include <va/va.h>\n\n/**\n * @file\n * API-specific header for AV_HWDEVICE_TYPE_VAAPI.\n *\n * Dynamic frame pools are supported, but note that any pool used as a render\n * target is required to be of fixed size in order to be be usable as an\n * argument to vaCreateContext().\n *\n * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs\n * with the data pointer set to a VASurfaceID.\n */\n\nenum {\n    /**\n     * The quirks field has been set by the user and should not be detected\n     * automatically by av_hwdevice_ctx_init().\n     */\n    AV_VAAPI_DRIVER_QUIRK_USER_SET = (1 << 0),\n    /**\n     * The driver does not destroy parameter buffers when they are used by\n     * vaRenderPicture().  Additional code will be required to destroy them\n     * separately afterwards.\n     */\n    AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS = (1 << 1),\n\n    /**\n     * The driver does not support the VASurfaceAttribMemoryType attribute,\n     * so the surface allocation code will not try to use it.\n     */\n    AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE = (1 << 2),\n\n    /**\n     * The driver does not support surface attributes at all.\n     * The surface allocation code will never pass them to surface allocation,\n     * and the results of the vaQuerySurfaceAttributes() call will be faked.\n     */\n    AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES = (1 << 3),\n};\n\n/**\n * VAAPI connection details.\n *\n * Allocated as AVHWDeviceContext.hwctx\n */\ntypedef struct AVVAAPIDeviceContext {\n    /**\n     * The VADisplay handle, to be filled by the user.\n     */\n    VADisplay display;\n    /**\n     * Driver quirks to apply - this is filled by av_hwdevice_ctx_init(),\n     * with reference to a table of known drivers, unless the\n     * AV_VAAPI_DRIVER_QUIRK_USER_SET bit is already present.  The user\n     * may need to refer to this field when performing any later\n     * operations using VAAPI with the same VADisplay.\n     */\n    unsigned int driver_quirks;\n} AVVAAPIDeviceContext;\n\n/**\n * VAAPI-specific data associated with a frame pool.\n *\n * Allocated as AVHWFramesContext.hwctx.\n */\ntypedef struct AVVAAPIFramesContext {\n    /**\n     * Set by the user to apply surface attributes to all surfaces in\n     * the frame pool.  If null, default settings are used.\n     */\n    VASurfaceAttrib *attributes;\n    int           nb_attributes;\n    /**\n     * The surfaces IDs of all surfaces in the pool after creation.\n     * Only valid if AVHWFramesContext.initial_pool_size was positive.\n     * These are intended to be used as the render_targets arguments to\n     * vaCreateContext().\n     */\n    VASurfaceID     *surface_ids;\n    int           nb_surfaces;\n} AVVAAPIFramesContext;\n\n/**\n * VAAPI hardware pipeline configuration details.\n *\n * Allocated with av_hwdevice_hwconfig_alloc().\n */\ntypedef struct AVVAAPIHWConfig {\n    /**\n     * ID of a VAAPI pipeline configuration.\n     */\n    VAConfigID config_id;\n} AVVAAPIHWConfig;\n\n#endif /* AVUTIL_HWCONTEXT_VAAPI_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_vdpau.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_VDPAU_H\n#define AVUTIL_HWCONTEXT_VDPAU_H\n\n#include <vdpau/vdpau.h>\n\n/**\n * @file\n * An API-specific header for AV_HWDEVICE_TYPE_VDPAU.\n *\n * This API supports dynamic frame pools. AVHWFramesContext.pool must return\n * AVBufferRefs whose data pointer is a VdpVideoSurface.\n */\n\n/**\n * This struct is allocated as AVHWDeviceContext.hwctx\n */\ntypedef struct AVVDPAUDeviceContext {\n    VdpDevice          device;\n    VdpGetProcAddress *get_proc_address;\n} AVVDPAUDeviceContext;\n\n/**\n * AVHWFramesContext.hwctx is currently not used\n */\n\n#endif /* AVUTIL_HWCONTEXT_VDPAU_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_videotoolbox.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H\n#define AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H\n\n#include <stdint.h>\n\n#include <VideoToolbox/VideoToolbox.h>\n\n#include \"pixfmt.h\"\n\n/**\n * @file\n * An API-specific header for AV_HWDEVICE_TYPE_VIDEOTOOLBOX.\n *\n * This API supports frame allocation using a native CVPixelBufferPool\n * instead of an AVBufferPool.\n *\n * If the API user sets a custom pool, AVHWFramesContext.pool must return\n * AVBufferRefs whose data pointer is a CVImageBufferRef or CVPixelBufferRef.\n * Note that the underlying CVPixelBuffer could be retained by OS frameworks\n * depending on application usage, so it is preferable to let CoreVideo manage\n * the pool using the default implementation.\n *\n * Currently AVHWDeviceContext.hwctx and AVHWFramesContext.hwctx are always\n * NULL.\n */\n\n/**\n * Convert a VideoToolbox (actually CoreVideo) format to AVPixelFormat.\n * Returns AV_PIX_FMT_NONE if no known equivalent was found.\n */\nenum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt);\n\n/**\n * Convert an AVPixelFormat to a VideoToolbox (actually CoreVideo) format.\n * Returns 0 if no known equivalent was found.\n */\nuint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt);\n\n/**\n * Same as av_map_videotoolbox_format_from_pixfmt function, but can map and\n * return full range pixel formats via a flag.\n */\nuint32_t av_map_videotoolbox_format_from_pixfmt2(enum AVPixelFormat pix_fmt, bool full_range);\n\n/**\n * Convert an AVChromaLocation to a VideoToolbox/CoreVideo chroma location string.\n * Returns 0 if no known equivalent was found.\n */\nCFStringRef av_map_videotoolbox_chroma_loc_from_av(enum AVChromaLocation loc);\n\n/**\n * Convert an AVColorSpace to a VideoToolbox/CoreVideo color matrix string.\n * Returns 0 if no known equivalent was found.\n */\nCFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space);\n\n/**\n * Convert an AVColorPrimaries to a VideoToolbox/CoreVideo color primaries string.\n * Returns 0 if no known equivalent was found.\n */\nCFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pri);\n\n/**\n * Convert an AVColorTransferCharacteristic to a VideoToolbox/CoreVideo color transfer\n * function string.\n * Returns 0 if no known equivalent was found.\n */\nCFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc);\n\n/**\n * Update a CVPixelBufferRef's metadata to based on an AVFrame.\n * Returns 0 if no known equivalent was found.\n */\nint av_vt_pixbuf_set_attachments(void *log_ctx,\n                                 CVPixelBufferRef pixbuf, const struct AVFrame *src);\n\n#endif /* AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/hwcontext_vulkan.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_HWCONTEXT_VULKAN_H\n#define AVUTIL_HWCONTEXT_VULKAN_H\n\n#if defined(_WIN32) && !defined(VK_USE_PLATFORM_WIN32_KHR)\n#define VK_USE_PLATFORM_WIN32_KHR\n#endif\n#include <vulkan/vulkan.h>\n\n#include \"pixfmt.h\"\n#include \"frame.h\"\n\n/**\n * @file\n * API-specific header for AV_HWDEVICE_TYPE_VULKAN.\n *\n * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs\n * with the data pointer set to an AVVkFrame.\n */\n\n/**\n * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.\n * All of these can be set before init to change what the context uses\n */\ntypedef struct AVVulkanDeviceContext {\n    /**\n     * Custom memory allocator, else NULL\n     */\n    const VkAllocationCallbacks *alloc;\n\n    /**\n     * Pointer to the instance-provided vkGetInstanceProcAddr loading function.\n     * If NULL, will pick either libvulkan or libvolk, depending on libavutil's\n     * compilation settings, and set this field.\n     */\n    PFN_vkGetInstanceProcAddr get_proc_addr;\n\n    /**\n     * Vulkan instance. Must be at least version 1.2.\n     */\n    VkInstance inst;\n\n    /**\n     * Physical device\n     */\n    VkPhysicalDevice phys_dev;\n\n    /**\n     * Active device\n     */\n    VkDevice act_dev;\n\n    /**\n     * This structure should be set to the set of features that present and enabled\n     * during device creation. When a device is created by FFmpeg, it will default to\n     * enabling all that are present of the shaderImageGatherExtended,\n     * fragmentStoresAndAtomics, shaderInt64 and vertexPipelineStoresAndAtomics features.\n     */\n    VkPhysicalDeviceFeatures2 device_features;\n\n    /**\n     * Enabled instance extensions.\n     * If supplying your own device context, set this to an array of strings, with\n     * each entry containing the specified Vulkan extension string to enable.\n     * Duplicates are possible and accepted.\n     * If no extensions are enabled, set these fields to NULL, and 0 respectively.\n     */\n    const char * const *enabled_inst_extensions;\n    int nb_enabled_inst_extensions;\n\n    /**\n     * Enabled device extensions. By default, VK_KHR_external_memory_fd,\n     * VK_EXT_external_memory_dma_buf, VK_EXT_image_drm_format_modifier,\n     * VK_KHR_external_semaphore_fd and VK_EXT_external_memory_host are enabled if found.\n     * If supplying your own device context, these fields takes the same format as\n     * the above fields, with the same conditions that duplicates are possible\n     * and accepted, and that NULL and 0 respectively means no extensions are enabled.\n     */\n    const char * const *enabled_dev_extensions;\n    int nb_enabled_dev_extensions;\n\n    /**\n     * Queue family index for graphics operations, and the number of queues\n     * enabled for it. If unavaiable, will be set to -1. Not required.\n     * av_hwdevice_create() will attempt to find a dedicated queue for each\n     * queue family, or pick the one with the least unrelated flags set.\n     * Queue indices here may overlap if a queue has to share capabilities.\n     */\n    int queue_family_index;\n    int nb_graphics_queues;\n\n    /**\n     * Queue family index for transfer operations and the number of queues\n     * enabled. Required.\n     */\n    int queue_family_tx_index;\n    int nb_tx_queues;\n\n    /**\n     * Queue family index for compute operations and the number of queues\n     * enabled. Required.\n     */\n    int queue_family_comp_index;\n    int nb_comp_queues;\n\n    /**\n     * Queue family index for video encode ops, and the amount of queues enabled.\n     * If the device doesn't support such, queue_family_encode_index will be -1.\n     * Not required.\n     */\n    int queue_family_encode_index;\n    int nb_encode_queues;\n\n    /**\n     * Queue family index for video decode ops, and the amount of queues enabled.\n     * If the device doesn't support such, queue_family_decode_index will be -1.\n     * Not required.\n     */\n    int queue_family_decode_index;\n    int nb_decode_queues;\n} AVVulkanDeviceContext;\n\n/**\n * Defines the behaviour of frame allocation.\n */\ntypedef enum AVVkFrameFlags {\n    /* Unless this flag is set, autodetected flags will be OR'd based on the\n     * device and tiling during av_hwframe_ctx_init(). */\n    AV_VK_FRAME_FLAG_NONE              = (1ULL << 0),\n\n    /* Image planes will be allocated in a single VkDeviceMemory, rather\n     * than as per-plane VkDeviceMemory allocations. Required for exporting\n     * to VAAPI on Intel devices. */\n    AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY = (1ULL << 1),\n} AVVkFrameFlags;\n\n/**\n * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options\n */\ntypedef struct AVVulkanFramesContext {\n    /**\n     * Controls the tiling of allocated frames. If left as optimal tiling,\n     * then during av_hwframe_ctx_init() will decide based on whether the device\n     * supports DRM modifiers, or if the linear_images flag is set, otherwise\n     * will allocate optimally-tiled images.\n     */\n    VkImageTiling tiling;\n\n    /**\n     * Defines extra usage of output frames. If left as 0, the following bits\n     * are set: TRANSFER_SRC, TRANSFER_DST. SAMPLED and STORAGE.\n     */\n    VkImageUsageFlagBits usage;\n\n    /**\n     * Extension data for image creation.\n     * If VkImageDrmFormatModifierListCreateInfoEXT is present in the chain,\n     * and the device supports DRM modifiers, then images will be allocated\n     * with the specific requested DRM modifiers.\n     * Additional structures may be added at av_hwframe_ctx_init() time,\n     * which will be freed automatically on uninit(), so users need only free\n     * any structures they've allocated themselves.\n     */\n    void *create_pnext;\n\n    /**\n     * Extension data for memory allocation. Must have as many entries as\n     * the number of planes of the sw_format.\n     * This will be chained to VkExportMemoryAllocateInfo, which is used\n     * to make all pool images exportable to other APIs if the necessary\n     * extensions are present in enabled_dev_extensions.\n     */\n    void *alloc_pnext[AV_NUM_DATA_POINTERS];\n\n    /**\n     * A combination of AVVkFrameFlags. Unless AV_VK_FRAME_FLAG_NONE is set,\n     * autodetected flags will be OR'd based on the device and tiling during\n     * av_hwframe_ctx_init().\n     */\n    AVVkFrameFlags flags;\n} AVVulkanFramesContext;\n\n/*\n * Frame structure, the VkFormat of the image will always match\n * the pool's sw_format.\n * All frames, imported or allocated, will be created with the\n * VK_IMAGE_CREATE_ALIAS_BIT flag set, so the memory may be aliased if needed.\n *\n * If all queue family indices in the device context are the same,\n * images will be created with the EXCLUSIVE sharing mode. Otherwise, all images\n * will be created using the CONCURRENT sharing mode.\n *\n * @note the size of this structure is not part of the ABI, to allocate\n * you must use @av_vk_frame_alloc().\n */\ntypedef struct AVVkFrame {\n    /**\n     * Vulkan images to which the memory is bound to.\n     */\n    VkImage img[AV_NUM_DATA_POINTERS];\n\n    /**\n     * The same tiling must be used for all images in the frame.\n     */\n    VkImageTiling tiling;\n\n    /**\n     * Memory backing the images. Could be less than the amount of planes,\n     * in which case the offset value will indicate the binding offset of\n     * each plane in the memory.\n     */\n    VkDeviceMemory mem[AV_NUM_DATA_POINTERS];\n    size_t size[AV_NUM_DATA_POINTERS];\n\n    /**\n     * OR'd flags for all memory allocated\n     */\n    VkMemoryPropertyFlagBits flags;\n\n    /**\n     * Updated after every barrier\n     */\n    VkAccessFlagBits access[AV_NUM_DATA_POINTERS];\n    VkImageLayout layout[AV_NUM_DATA_POINTERS];\n\n    /**\n     * Synchronization timeline semaphores, one for each sw_format plane.\n     * Must not be freed manually. Must be waited on at every submission using\n     * the value in sem_value, and must be signalled at every submission,\n     * using an incremented value.\n     */\n    VkSemaphore sem[AV_NUM_DATA_POINTERS];\n\n    /**\n     * Up to date semaphore value at which each image becomes accessible.\n     * Clients must wait on this value when submitting a command queue,\n     * and increment it when signalling.\n     */\n    uint64_t sem_value[AV_NUM_DATA_POINTERS];\n\n    /**\n     * Internal data.\n     */\n    struct AVVkFrameInternal *internal;\n\n    /**\n     * Describes the binding offset of each plane to the VkDeviceMemory.\n     */\n    ptrdiff_t offset[AV_NUM_DATA_POINTERS];\n} AVVkFrame;\n\n/**\n * Allocates a single AVVkFrame and initializes everything as 0.\n * @note Must be freed via av_free()\n */\nAVVkFrame *av_vk_frame_alloc(void);\n\n/**\n * Returns the format of each image up to the number of planes for a given sw_format.\n * Returns NULL on unsupported formats.\n */\nconst VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p);\n\n#endif /* AVUTIL_HWCONTEXT_VULKAN_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/imgutils.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_IMGUTILS_H\n#define AVUTIL_IMGUTILS_H\n\n/**\n * @file\n * misc image utilities\n *\n * @addtogroup lavu_picture\n * @{\n */\n\n#include <stddef.h>\n#include <stdint.h>\n#include \"pixdesc.h\"\n#include \"pixfmt.h\"\n#include \"rational.h\"\n\n/**\n * Compute the max pixel step for each plane of an image with a\n * format described by pixdesc.\n *\n * The pixel step is the distance in bytes between the first byte of\n * the group of bytes which describe a pixel component and the first\n * byte of the successive group in the same plane for the same\n * component.\n *\n * @param max_pixsteps an array which is filled with the max pixel step\n * for each plane. Since a plane may contain different pixel\n * components, the computed max_pixsteps[plane] is relative to the\n * component in the plane with the max pixel step.\n * @param max_pixstep_comps an array which is filled with the component\n * for each plane which has the max pixel step. May be NULL.\n */\nvoid av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4],\n                                const AVPixFmtDescriptor *pixdesc);\n\n/**\n * Compute the size of an image line with format pix_fmt and width\n * width for the plane plane.\n *\n * @return the computed size in bytes\n */\nint av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane);\n\n/**\n * Fill plane linesizes for an image with pixel format pix_fmt and\n * width width.\n *\n * @param linesizes array to be filled with the linesize for each plane\n * @return >= 0 in case of success, a negative error code otherwise\n */\nint av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width);\n\n/**\n * Fill plane sizes for an image with pixel format pix_fmt and height height.\n *\n * @param size the array to be filled with the size of each image plane\n * @param linesizes the array containing the linesize for each\n *        plane, should be filled by av_image_fill_linesizes()\n * @return >= 0 in case of success, a negative error code otherwise\n *\n * @note The linesize parameters have the type ptrdiff_t here, while they are\n *       int for av_image_fill_linesizes().\n */\nint av_image_fill_plane_sizes(size_t size[4], enum AVPixelFormat pix_fmt,\n                              int height, const ptrdiff_t linesizes[4]);\n\n/**\n * Fill plane data pointers for an image with pixel format pix_fmt and\n * height height.\n *\n * @param data pointers array to be filled with the pointer for each image plane\n * @param ptr the pointer to a buffer which will contain the image\n * @param linesizes the array containing the linesize for each\n * plane, should be filled by av_image_fill_linesizes()\n * @return the size in bytes required for the image buffer, a negative\n * error code in case of failure\n */\nint av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height,\n                           uint8_t *ptr, const int linesizes[4]);\n\n/**\n * Allocate an image with size w and h and pixel format pix_fmt, and\n * fill pointers and linesizes accordingly.\n * The allocated image buffer has to be freed by using\n * av_freep(&pointers[0]).\n *\n * @param align the value to use for buffer size alignment\n * @return the size in bytes required for the image buffer, a negative\n * error code in case of failure\n */\nint av_image_alloc(uint8_t *pointers[4], int linesizes[4],\n                   int w, int h, enum AVPixelFormat pix_fmt, int align);\n\n/**\n * Copy image plane from src to dst.\n * That is, copy \"height\" number of lines of \"bytewidth\" bytes each.\n * The first byte of each successive line is separated by *_linesize\n * bytes.\n *\n * bytewidth must be contained by both absolute values of dst_linesize\n * and src_linesize, otherwise the function behavior is undefined.\n *\n * @param dst_linesize linesize for the image plane in dst\n * @param src_linesize linesize for the image plane in src\n */\nvoid av_image_copy_plane(uint8_t       *dst, int dst_linesize,\n                         const uint8_t *src, int src_linesize,\n                         int bytewidth, int height);\n\n/**\n * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where\n * available, this function will use special functionality for reading from such\n * memory, which may result in greatly improved performance compared to plain\n * av_image_copy_plane().\n *\n * bytewidth must be contained by both absolute values of dst_linesize\n * and src_linesize, otherwise the function behavior is undefined.\n *\n * @note The linesize parameters have the type ptrdiff_t here, while they are\n *       int for av_image_copy_plane().\n * @note On x86, the linesizes currently need to be aligned to the cacheline\n *       size (i.e. 64) to get improved performance.\n */\nvoid av_image_copy_plane_uc_from(uint8_t       *dst, ptrdiff_t dst_linesize,\n                                 const uint8_t *src, ptrdiff_t src_linesize,\n                                 ptrdiff_t bytewidth, int height);\n\n/**\n * Copy image in src_data to dst_data.\n *\n * @param dst_linesizes linesizes for the image in dst_data\n * @param src_linesizes linesizes for the image in src_data\n */\nvoid av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],\n                   const uint8_t *src_data[4], const int src_linesizes[4],\n                   enum AVPixelFormat pix_fmt, int width, int height);\n\n/**\n * Copy image data located in uncacheable (e.g. GPU mapped) memory. Where\n * available, this function will use special functionality for reading from such\n * memory, which may result in greatly improved performance compared to plain\n * av_image_copy().\n *\n * The data pointers and the linesizes must be aligned to the maximum required\n * by the CPU architecture.\n *\n * @note The linesize parameters have the type ptrdiff_t here, while they are\n *       int for av_image_copy().\n * @note On x86, the linesizes currently need to be aligned to the cacheline\n *       size (i.e. 64) to get improved performance.\n */\nvoid av_image_copy_uc_from(uint8_t *dst_data[4],       const ptrdiff_t dst_linesizes[4],\n                           const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],\n                           enum AVPixelFormat pix_fmt, int width, int height);\n\n/**\n * Setup the data pointers and linesizes based on the specified image\n * parameters and the provided array.\n *\n * The fields of the given image are filled in by using the src\n * address which points to the image data buffer. Depending on the\n * specified pixel format, one or multiple image data pointers and\n * line sizes will be set.  If a planar format is specified, several\n * pointers will be set pointing to the different picture planes and\n * the line sizes of the different planes will be stored in the\n * lines_sizes array. Call with src == NULL to get the required\n * size for the src buffer.\n *\n * To allocate the buffer and fill in the dst_data and dst_linesize in\n * one call, use av_image_alloc().\n *\n * @param dst_data      data pointers to be filled in\n * @param dst_linesize  linesizes for the image in dst_data to be filled in\n * @param src           buffer which will contain or contains the actual image data, can be NULL\n * @param pix_fmt       the pixel format of the image\n * @param width         the width of the image in pixels\n * @param height        the height of the image in pixels\n * @param align         the value used in src for linesize alignment\n * @return the size in bytes required for src, a negative error code\n * in case of failure\n */\nint av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],\n                         const uint8_t *src,\n                         enum AVPixelFormat pix_fmt, int width, int height, int align);\n\n/**\n * Return the size in bytes of the amount of data required to store an\n * image with the given parameters.\n *\n * @param pix_fmt  the pixel format of the image\n * @param width    the width of the image in pixels\n * @param height   the height of the image in pixels\n * @param align    the assumed linesize alignment\n * @return the buffer size in bytes, a negative error code in case of failure\n */\nint av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align);\n\n/**\n * Copy image data from an image into a buffer.\n *\n * av_image_get_buffer_size() can be used to compute the required size\n * for the buffer to fill.\n *\n * @param dst           a buffer into which picture data will be copied\n * @param dst_size      the size in bytes of dst\n * @param src_data      pointers containing the source image data\n * @param src_linesize  linesizes for the image in src_data\n * @param pix_fmt       the pixel format of the source image\n * @param width         the width of the source image in pixels\n * @param height        the height of the source image in pixels\n * @param align         the assumed linesize alignment for dst\n * @return the number of bytes written to dst, or a negative value\n * (error code) on error\n */\nint av_image_copy_to_buffer(uint8_t *dst, int dst_size,\n                            const uint8_t * const src_data[4], const int src_linesize[4],\n                            enum AVPixelFormat pix_fmt, int width, int height, int align);\n\n/**\n * Check if the given dimension of an image is valid, meaning that all\n * bytes of the image can be addressed with a signed int.\n *\n * @param w the width of the picture\n * @param h the height of the picture\n * @param log_offset the offset to sum to the log level for logging with log_ctx\n * @param log_ctx the parent logging context, it may be NULL\n * @return >= 0 if valid, a negative error code otherwise\n */\nint av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx);\n\n/**\n * Check if the given dimension of an image is valid, meaning that all\n * bytes of a plane of an image with the specified pix_fmt can be addressed\n * with a signed int.\n *\n * @param w the width of the picture\n * @param h the height of the picture\n * @param max_pixels the maximum number of pixels the user wants to accept\n * @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown.\n * @param log_offset the offset to sum to the log level for logging with log_ctx\n * @param log_ctx the parent logging context, it may be NULL\n * @return >= 0 if valid, a negative error code otherwise\n */\nint av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx);\n\n/**\n * Check if the given sample aspect ratio of an image is valid.\n *\n * It is considered invalid if the denominator is 0 or if applying the ratio\n * to the image size would make the smaller dimension less than 1. If the\n * sar numerator is 0, it is considered unknown and will return as valid.\n *\n * @param w width of the image\n * @param h height of the image\n * @param sar sample aspect ratio of the image\n * @return 0 if valid, a negative AVERROR code otherwise\n */\nint av_image_check_sar(unsigned int w, unsigned int h, AVRational sar);\n\n/**\n * Overwrite the image data with black. This is suitable for filling a\n * sub-rectangle of an image, meaning the padding between the right most pixel\n * and the left most pixel on the next line will not be overwritten. For some\n * formats, the image size might be rounded up due to inherent alignment.\n *\n * If the pixel format has alpha, the alpha is cleared to opaque.\n *\n * This can return an error if the pixel format is not supported. Normally, all\n * non-hwaccel pixel formats should be supported.\n *\n * Passing NULL for dst_data is allowed. Then the function returns whether the\n * operation would have succeeded. (It can return an error if the pix_fmt is\n * not supported.)\n *\n * @param dst_data      data pointers to destination image\n * @param dst_linesize  linesizes for the destination image\n * @param pix_fmt       the pixel format of the image\n * @param range         the color range of the image (important for colorspaces such as YUV)\n * @param width         the width of the image in pixels\n * @param height        the height of the image in pixels\n * @return 0 if the image data was cleared, a negative AVERROR code otherwise\n */\nint av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4],\n                        enum AVPixelFormat pix_fmt, enum AVColorRange range,\n                        int width, int height);\n\n/**\n * @}\n */\n\n\n#endif /* AVUTIL_IMGUTILS_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/intfloat.h",
    "content": "/*\n * Copyright (c) 2011 Mans Rullgard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_INTFLOAT_H\n#define AVUTIL_INTFLOAT_H\n\n#include <stdint.h>\n#include \"attributes.h\"\n\nunion av_intfloat32 {\n    uint32_t i;\n    float    f;\n};\n\nunion av_intfloat64 {\n    uint64_t i;\n    double   f;\n};\n\n/**\n * Reinterpret a 32-bit integer as a float.\n */\nstatic av_always_inline float av_int2float(uint32_t i)\n{\n    union av_intfloat32 v;\n    v.i = i;\n    return v.f;\n}\n\n/**\n * Reinterpret a float as a 32-bit integer.\n */\nstatic av_always_inline uint32_t av_float2int(float f)\n{\n    union av_intfloat32 v;\n    v.f = f;\n    return v.i;\n}\n\n/**\n * Reinterpret a 64-bit integer as a double.\n */\nstatic av_always_inline double av_int2double(uint64_t i)\n{\n    union av_intfloat64 v;\n    v.i = i;\n    return v.f;\n}\n\n/**\n * Reinterpret a double as a 64-bit integer.\n */\nstatic av_always_inline uint64_t av_double2int(double f)\n{\n    union av_intfloat64 v;\n    v.f = f;\n    return v.i;\n}\n\n#endif /* AVUTIL_INTFLOAT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/intreadwrite.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_INTREADWRITE_H\n#define AVUTIL_INTREADWRITE_H\n\n#include <stdint.h>\n#include \"libavutil/avconfig.h\"\n#include \"attributes.h\"\n#include \"bswap.h\"\n\ntypedef union {\n    uint64_t u64;\n    uint32_t u32[2];\n    uint16_t u16[4];\n    uint8_t  u8 [8];\n    double   f64;\n    float    f32[2];\n} av_alias av_alias64;\n\ntypedef union {\n    uint32_t u32;\n    uint16_t u16[2];\n    uint8_t  u8 [4];\n    float    f32;\n} av_alias av_alias32;\n\ntypedef union {\n    uint16_t u16;\n    uint8_t  u8 [2];\n} av_alias av_alias16;\n\n/*\n * Arch-specific headers can provide any combination of\n * AV_[RW][BLN](16|24|32|48|64) and AV_(COPY|SWAP|ZERO)(64|128) macros.\n * Preprocessor symbols must be defined, even if these are implemented\n * as inline functions.\n *\n * R/W means read/write, B/L/N means big/little/native endianness.\n * The following macros require aligned access, compared to their\n * unaligned variants: AV_(COPY|SWAP|ZERO)(64|128), AV_[RW]N[8-64]A.\n * Incorrect usage may range from abysmal performance to crash\n * depending on the platform.\n *\n * The unaligned variants are AV_[RW][BLN][8-64] and AV_COPY*U.\n */\n\n#ifdef HAVE_AV_CONFIG_H\n\n#include \"config.h\"\n\n#if   ARCH_ARM\n#   include \"arm/intreadwrite.h\"\n#elif ARCH_AVR32\n#   include \"avr32/intreadwrite.h\"\n#elif ARCH_MIPS\n#   include \"mips/intreadwrite.h\"\n#elif ARCH_PPC\n#   include \"ppc/intreadwrite.h\"\n#elif ARCH_TOMI\n#   include \"tomi/intreadwrite.h\"\n#elif ARCH_X86\n#   include \"x86/intreadwrite.h\"\n#endif\n\n#endif /* HAVE_AV_CONFIG_H */\n\n/*\n * Map AV_RNXX <-> AV_R[BL]XX for all variants provided by per-arch headers.\n */\n\n#if AV_HAVE_BIGENDIAN\n\n#   if    defined(AV_RN16) && !defined(AV_RB16)\n#       define AV_RB16(p) AV_RN16(p)\n#   elif !defined(AV_RN16) &&  defined(AV_RB16)\n#       define AV_RN16(p) AV_RB16(p)\n#   endif\n\n#   if    defined(AV_WN16) && !defined(AV_WB16)\n#       define AV_WB16(p, v) AV_WN16(p, v)\n#   elif !defined(AV_WN16) &&  defined(AV_WB16)\n#       define AV_WN16(p, v) AV_WB16(p, v)\n#   endif\n\n#   if    defined(AV_RN24) && !defined(AV_RB24)\n#       define AV_RB24(p) AV_RN24(p)\n#   elif !defined(AV_RN24) &&  defined(AV_RB24)\n#       define AV_RN24(p) AV_RB24(p)\n#   endif\n\n#   if    defined(AV_WN24) && !defined(AV_WB24)\n#       define AV_WB24(p, v) AV_WN24(p, v)\n#   elif !defined(AV_WN24) &&  defined(AV_WB24)\n#       define AV_WN24(p, v) AV_WB24(p, v)\n#   endif\n\n#   if    defined(AV_RN32) && !defined(AV_RB32)\n#       define AV_RB32(p) AV_RN32(p)\n#   elif !defined(AV_RN32) &&  defined(AV_RB32)\n#       define AV_RN32(p) AV_RB32(p)\n#   endif\n\n#   if    defined(AV_WN32) && !defined(AV_WB32)\n#       define AV_WB32(p, v) AV_WN32(p, v)\n#   elif !defined(AV_WN32) &&  defined(AV_WB32)\n#       define AV_WN32(p, v) AV_WB32(p, v)\n#   endif\n\n#   if    defined(AV_RN48) && !defined(AV_RB48)\n#       define AV_RB48(p) AV_RN48(p)\n#   elif !defined(AV_RN48) &&  defined(AV_RB48)\n#       define AV_RN48(p) AV_RB48(p)\n#   endif\n\n#   if    defined(AV_WN48) && !defined(AV_WB48)\n#       define AV_WB48(p, v) AV_WN48(p, v)\n#   elif !defined(AV_WN48) &&  defined(AV_WB48)\n#       define AV_WN48(p, v) AV_WB48(p, v)\n#   endif\n\n#   if    defined(AV_RN64) && !defined(AV_RB64)\n#       define AV_RB64(p) AV_RN64(p)\n#   elif !defined(AV_RN64) &&  defined(AV_RB64)\n#       define AV_RN64(p) AV_RB64(p)\n#   endif\n\n#   if    defined(AV_WN64) && !defined(AV_WB64)\n#       define AV_WB64(p, v) AV_WN64(p, v)\n#   elif !defined(AV_WN64) &&  defined(AV_WB64)\n#       define AV_WN64(p, v) AV_WB64(p, v)\n#   endif\n\n#else /* AV_HAVE_BIGENDIAN */\n\n#   if    defined(AV_RN16) && !defined(AV_RL16)\n#       define AV_RL16(p) AV_RN16(p)\n#   elif !defined(AV_RN16) &&  defined(AV_RL16)\n#       define AV_RN16(p) AV_RL16(p)\n#   endif\n\n#   if    defined(AV_WN16) && !defined(AV_WL16)\n#       define AV_WL16(p, v) AV_WN16(p, v)\n#   elif !defined(AV_WN16) &&  defined(AV_WL16)\n#       define AV_WN16(p, v) AV_WL16(p, v)\n#   endif\n\n#   if    defined(AV_RN24) && !defined(AV_RL24)\n#       define AV_RL24(p) AV_RN24(p)\n#   elif !defined(AV_RN24) &&  defined(AV_RL24)\n#       define AV_RN24(p) AV_RL24(p)\n#   endif\n\n#   if    defined(AV_WN24) && !defined(AV_WL24)\n#       define AV_WL24(p, v) AV_WN24(p, v)\n#   elif !defined(AV_WN24) &&  defined(AV_WL24)\n#       define AV_WN24(p, v) AV_WL24(p, v)\n#   endif\n\n#   if    defined(AV_RN32) && !defined(AV_RL32)\n#       define AV_RL32(p) AV_RN32(p)\n#   elif !defined(AV_RN32) &&  defined(AV_RL32)\n#       define AV_RN32(p) AV_RL32(p)\n#   endif\n\n#   if    defined(AV_WN32) && !defined(AV_WL32)\n#       define AV_WL32(p, v) AV_WN32(p, v)\n#   elif !defined(AV_WN32) &&  defined(AV_WL32)\n#       define AV_WN32(p, v) AV_WL32(p, v)\n#   endif\n\n#   if    defined(AV_RN48) && !defined(AV_RL48)\n#       define AV_RL48(p) AV_RN48(p)\n#   elif !defined(AV_RN48) &&  defined(AV_RL48)\n#       define AV_RN48(p) AV_RL48(p)\n#   endif\n\n#   if    defined(AV_WN48) && !defined(AV_WL48)\n#       define AV_WL48(p, v) AV_WN48(p, v)\n#   elif !defined(AV_WN48) &&  defined(AV_WL48)\n#       define AV_WN48(p, v) AV_WL48(p, v)\n#   endif\n\n#   if    defined(AV_RN64) && !defined(AV_RL64)\n#       define AV_RL64(p) AV_RN64(p)\n#   elif !defined(AV_RN64) &&  defined(AV_RL64)\n#       define AV_RN64(p) AV_RL64(p)\n#   endif\n\n#   if    defined(AV_WN64) && !defined(AV_WL64)\n#       define AV_WL64(p, v) AV_WN64(p, v)\n#   elif !defined(AV_WN64) &&  defined(AV_WL64)\n#       define AV_WN64(p, v) AV_WL64(p, v)\n#   endif\n\n#endif /* !AV_HAVE_BIGENDIAN */\n\n/*\n * Define AV_[RW]N helper macros to simplify definitions not provided\n * by per-arch headers.\n */\n\n#if defined(__GNUC__)\n\nunion unaligned_64 { uint64_t l; } __attribute__((packed)) av_alias;\nunion unaligned_32 { uint32_t l; } __attribute__((packed)) av_alias;\nunion unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias;\n\n#   define AV_RN(s, p) (((const union unaligned_##s *) (p))->l)\n#   define AV_WN(s, p, v) ((((union unaligned_##s *) (p))->l) = (v))\n\n#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_X64) || defined(_M_ARM64)) && AV_HAVE_FAST_UNALIGNED\n\n#   define AV_RN(s, p) (*((const __unaligned uint##s##_t*)(p)))\n#   define AV_WN(s, p, v) (*((__unaligned uint##s##_t*)(p)) = (v))\n\n#elif AV_HAVE_FAST_UNALIGNED\n\n#   define AV_RN(s, p) (((const av_alias##s*)(p))->u##s)\n#   define AV_WN(s, p, v) (((av_alias##s*)(p))->u##s = (v))\n\n#else\n\n#ifndef AV_RB16\n#   define AV_RB16(x)                           \\\n    ((((const uint8_t*)(x))[0] << 8) |          \\\n      ((const uint8_t*)(x))[1])\n#endif\n#ifndef AV_WB16\n#   define AV_WB16(p, val) do {                 \\\n        uint16_t d = (val);                     \\\n        ((uint8_t*)(p))[1] = (d);               \\\n        ((uint8_t*)(p))[0] = (d)>>8;            \\\n    } while(0)\n#endif\n\n#ifndef AV_RL16\n#   define AV_RL16(x)                           \\\n    ((((const uint8_t*)(x))[1] << 8) |          \\\n      ((const uint8_t*)(x))[0])\n#endif\n#ifndef AV_WL16\n#   define AV_WL16(p, val) do {                 \\\n        uint16_t d = (val);                     \\\n        ((uint8_t*)(p))[0] = (d);               \\\n        ((uint8_t*)(p))[1] = (d)>>8;            \\\n    } while(0)\n#endif\n\n#ifndef AV_RB32\n#   define AV_RB32(x)                                \\\n    (((uint32_t)((const uint8_t*)(x))[0] << 24) |    \\\n               (((const uint8_t*)(x))[1] << 16) |    \\\n               (((const uint8_t*)(x))[2] <<  8) |    \\\n                ((const uint8_t*)(x))[3])\n#endif\n#ifndef AV_WB32\n#   define AV_WB32(p, val) do {                 \\\n        uint32_t d = (val);                     \\\n        ((uint8_t*)(p))[3] = (d);               \\\n        ((uint8_t*)(p))[2] = (d)>>8;            \\\n        ((uint8_t*)(p))[1] = (d)>>16;           \\\n        ((uint8_t*)(p))[0] = (d)>>24;           \\\n    } while(0)\n#endif\n\n#ifndef AV_RL32\n#   define AV_RL32(x)                                \\\n    (((uint32_t)((const uint8_t*)(x))[3] << 24) |    \\\n               (((const uint8_t*)(x))[2] << 16) |    \\\n               (((const uint8_t*)(x))[1] <<  8) |    \\\n                ((const uint8_t*)(x))[0])\n#endif\n#ifndef AV_WL32\n#   define AV_WL32(p, val) do {                 \\\n        uint32_t d = (val);                     \\\n        ((uint8_t*)(p))[0] = (d);               \\\n        ((uint8_t*)(p))[1] = (d)>>8;            \\\n        ((uint8_t*)(p))[2] = (d)>>16;           \\\n        ((uint8_t*)(p))[3] = (d)>>24;           \\\n    } while(0)\n#endif\n\n#ifndef AV_RB64\n#   define AV_RB64(x)                                   \\\n    (((uint64_t)((const uint8_t*)(x))[0] << 56) |       \\\n     ((uint64_t)((const uint8_t*)(x))[1] << 48) |       \\\n     ((uint64_t)((const uint8_t*)(x))[2] << 40) |       \\\n     ((uint64_t)((const uint8_t*)(x))[3] << 32) |       \\\n     ((uint64_t)((const uint8_t*)(x))[4] << 24) |       \\\n     ((uint64_t)((const uint8_t*)(x))[5] << 16) |       \\\n     ((uint64_t)((const uint8_t*)(x))[6] <<  8) |       \\\n      (uint64_t)((const uint8_t*)(x))[7])\n#endif\n#ifndef AV_WB64\n#   define AV_WB64(p, val) do {                 \\\n        uint64_t d = (val);                     \\\n        ((uint8_t*)(p))[7] = (d);               \\\n        ((uint8_t*)(p))[6] = (d)>>8;            \\\n        ((uint8_t*)(p))[5] = (d)>>16;           \\\n        ((uint8_t*)(p))[4] = (d)>>24;           \\\n        ((uint8_t*)(p))[3] = (d)>>32;           \\\n        ((uint8_t*)(p))[2] = (d)>>40;           \\\n        ((uint8_t*)(p))[1] = (d)>>48;           \\\n        ((uint8_t*)(p))[0] = (d)>>56;           \\\n    } while(0)\n#endif\n\n#ifndef AV_RL64\n#   define AV_RL64(x)                                   \\\n    (((uint64_t)((const uint8_t*)(x))[7] << 56) |       \\\n     ((uint64_t)((const uint8_t*)(x))[6] << 48) |       \\\n     ((uint64_t)((const uint8_t*)(x))[5] << 40) |       \\\n     ((uint64_t)((const uint8_t*)(x))[4] << 32) |       \\\n     ((uint64_t)((const uint8_t*)(x))[3] << 24) |       \\\n     ((uint64_t)((const uint8_t*)(x))[2] << 16) |       \\\n     ((uint64_t)((const uint8_t*)(x))[1] <<  8) |       \\\n      (uint64_t)((const uint8_t*)(x))[0])\n#endif\n#ifndef AV_WL64\n#   define AV_WL64(p, val) do {                 \\\n        uint64_t d = (val);                     \\\n        ((uint8_t*)(p))[0] = (d);               \\\n        ((uint8_t*)(p))[1] = (d)>>8;            \\\n        ((uint8_t*)(p))[2] = (d)>>16;           \\\n        ((uint8_t*)(p))[3] = (d)>>24;           \\\n        ((uint8_t*)(p))[4] = (d)>>32;           \\\n        ((uint8_t*)(p))[5] = (d)>>40;           \\\n        ((uint8_t*)(p))[6] = (d)>>48;           \\\n        ((uint8_t*)(p))[7] = (d)>>56;           \\\n    } while(0)\n#endif\n\n#if AV_HAVE_BIGENDIAN\n#   define AV_RN(s, p)    AV_RB##s(p)\n#   define AV_WN(s, p, v) AV_WB##s(p, v)\n#else\n#   define AV_RN(s, p)    AV_RL##s(p)\n#   define AV_WN(s, p, v) AV_WL##s(p, v)\n#endif\n\n#endif /* HAVE_FAST_UNALIGNED */\n\n#ifndef AV_RN16\n#   define AV_RN16(p) AV_RN(16, p)\n#endif\n\n#ifndef AV_RN32\n#   define AV_RN32(p) AV_RN(32, p)\n#endif\n\n#ifndef AV_RN64\n#   define AV_RN64(p) AV_RN(64, p)\n#endif\n\n#ifndef AV_WN16\n#   define AV_WN16(p, v) AV_WN(16, p, v)\n#endif\n\n#ifndef AV_WN32\n#   define AV_WN32(p, v) AV_WN(32, p, v)\n#endif\n\n#ifndef AV_WN64\n#   define AV_WN64(p, v) AV_WN(64, p, v)\n#endif\n\n#if AV_HAVE_BIGENDIAN\n#   define AV_RB(s, p)    AV_RN##s(p)\n#   define AV_WB(s, p, v) AV_WN##s(p, v)\n#   define AV_RL(s, p)    av_bswap##s(AV_RN##s(p))\n#   define AV_WL(s, p, v) AV_WN##s(p, av_bswap##s(v))\n#else\n#   define AV_RB(s, p)    av_bswap##s(AV_RN##s(p))\n#   define AV_WB(s, p, v) AV_WN##s(p, av_bswap##s(v))\n#   define AV_RL(s, p)    AV_RN##s(p)\n#   define AV_WL(s, p, v) AV_WN##s(p, v)\n#endif\n\n#define AV_RB8(x)     (((const uint8_t*)(x))[0])\n#define AV_WB8(p, d)  do { ((uint8_t*)(p))[0] = (d); } while(0)\n\n#define AV_RL8(x)     AV_RB8(x)\n#define AV_WL8(p, d)  AV_WB8(p, d)\n\n#ifndef AV_RB16\n#   define AV_RB16(p)    AV_RB(16, p)\n#endif\n#ifndef AV_WB16\n#   define AV_WB16(p, v) AV_WB(16, p, v)\n#endif\n\n#ifndef AV_RL16\n#   define AV_RL16(p)    AV_RL(16, p)\n#endif\n#ifndef AV_WL16\n#   define AV_WL16(p, v) AV_WL(16, p, v)\n#endif\n\n#ifndef AV_RB32\n#   define AV_RB32(p)    AV_RB(32, p)\n#endif\n#ifndef AV_WB32\n#   define AV_WB32(p, v) AV_WB(32, p, v)\n#endif\n\n#ifndef AV_RL32\n#   define AV_RL32(p)    AV_RL(32, p)\n#endif\n#ifndef AV_WL32\n#   define AV_WL32(p, v) AV_WL(32, p, v)\n#endif\n\n#ifndef AV_RB64\n#   define AV_RB64(p)    AV_RB(64, p)\n#endif\n#ifndef AV_WB64\n#   define AV_WB64(p, v) AV_WB(64, p, v)\n#endif\n\n#ifndef AV_RL64\n#   define AV_RL64(p)    AV_RL(64, p)\n#endif\n#ifndef AV_WL64\n#   define AV_WL64(p, v) AV_WL(64, p, v)\n#endif\n\n#ifndef AV_RB24\n#   define AV_RB24(x)                           \\\n    ((((const uint8_t*)(x))[0] << 16) |         \\\n     (((const uint8_t*)(x))[1] <<  8) |         \\\n      ((const uint8_t*)(x))[2])\n#endif\n#ifndef AV_WB24\n#   define AV_WB24(p, d) do {                   \\\n        ((uint8_t*)(p))[2] = (d);               \\\n        ((uint8_t*)(p))[1] = (d)>>8;            \\\n        ((uint8_t*)(p))[0] = (d)>>16;           \\\n    } while(0)\n#endif\n\n#ifndef AV_RL24\n#   define AV_RL24(x)                           \\\n    ((((const uint8_t*)(x))[2] << 16) |         \\\n     (((const uint8_t*)(x))[1] <<  8) |         \\\n      ((const uint8_t*)(x))[0])\n#endif\n#ifndef AV_WL24\n#   define AV_WL24(p, d) do {                   \\\n        ((uint8_t*)(p))[0] = (d);               \\\n        ((uint8_t*)(p))[1] = (d)>>8;            \\\n        ((uint8_t*)(p))[2] = (d)>>16;           \\\n    } while(0)\n#endif\n\n#ifndef AV_RB48\n#   define AV_RB48(x)                                     \\\n    (((uint64_t)((const uint8_t*)(x))[0] << 40) |         \\\n     ((uint64_t)((const uint8_t*)(x))[1] << 32) |         \\\n     ((uint64_t)((const uint8_t*)(x))[2] << 24) |         \\\n     ((uint64_t)((const uint8_t*)(x))[3] << 16) |         \\\n     ((uint64_t)((const uint8_t*)(x))[4] <<  8) |         \\\n      (uint64_t)((const uint8_t*)(x))[5])\n#endif\n#ifndef AV_WB48\n#   define AV_WB48(p, darg) do {                \\\n        uint64_t d = (darg);                    \\\n        ((uint8_t*)(p))[5] = (d);               \\\n        ((uint8_t*)(p))[4] = (d)>>8;            \\\n        ((uint8_t*)(p))[3] = (d)>>16;           \\\n        ((uint8_t*)(p))[2] = (d)>>24;           \\\n        ((uint8_t*)(p))[1] = (d)>>32;           \\\n        ((uint8_t*)(p))[0] = (d)>>40;           \\\n    } while(0)\n#endif\n\n#ifndef AV_RL48\n#   define AV_RL48(x)                                     \\\n    (((uint64_t)((const uint8_t*)(x))[5] << 40) |         \\\n     ((uint64_t)((const uint8_t*)(x))[4] << 32) |         \\\n     ((uint64_t)((const uint8_t*)(x))[3] << 24) |         \\\n     ((uint64_t)((const uint8_t*)(x))[2] << 16) |         \\\n     ((uint64_t)((const uint8_t*)(x))[1] <<  8) |         \\\n      (uint64_t)((const uint8_t*)(x))[0])\n#endif\n#ifndef AV_WL48\n#   define AV_WL48(p, darg) do {                \\\n        uint64_t d = (darg);                    \\\n        ((uint8_t*)(p))[0] = (d);               \\\n        ((uint8_t*)(p))[1] = (d)>>8;            \\\n        ((uint8_t*)(p))[2] = (d)>>16;           \\\n        ((uint8_t*)(p))[3] = (d)>>24;           \\\n        ((uint8_t*)(p))[4] = (d)>>32;           \\\n        ((uint8_t*)(p))[5] = (d)>>40;           \\\n    } while(0)\n#endif\n\n/*\n * The AV_[RW]NA macros access naturally aligned data\n * in a type-safe way.\n */\n\n#define AV_RNA(s, p)    (((const av_alias##s*)(p))->u##s)\n#define AV_WNA(s, p, v) (((av_alias##s*)(p))->u##s = (v))\n\n#ifndef AV_RN16A\n#   define AV_RN16A(p) AV_RNA(16, p)\n#endif\n\n#ifndef AV_RN32A\n#   define AV_RN32A(p) AV_RNA(32, p)\n#endif\n\n#ifndef AV_RN64A\n#   define AV_RN64A(p) AV_RNA(64, p)\n#endif\n\n#ifndef AV_WN16A\n#   define AV_WN16A(p, v) AV_WNA(16, p, v)\n#endif\n\n#ifndef AV_WN32A\n#   define AV_WN32A(p, v) AV_WNA(32, p, v)\n#endif\n\n#ifndef AV_WN64A\n#   define AV_WN64A(p, v) AV_WNA(64, p, v)\n#endif\n\n#if AV_HAVE_BIGENDIAN\n#   define AV_RLA(s, p)    av_bswap##s(AV_RN##s##A(p))\n#   define AV_WLA(s, p, v) AV_WN##s##A(p, av_bswap##s(v))\n#else\n#   define AV_RLA(s, p)    AV_RN##s##A(p)\n#   define AV_WLA(s, p, v) AV_WN##s##A(p, v)\n#endif\n\n#ifndef AV_RL64A\n#   define AV_RL64A(p) AV_RLA(64, p)\n#endif\n#ifndef AV_WL64A\n#   define AV_WL64A(p, v) AV_WLA(64, p, v)\n#endif\n\n/*\n * The AV_COPYxxU macros are suitable for copying data to/from unaligned\n * memory locations.\n */\n\n#define AV_COPYU(n, d, s) AV_WN##n(d, AV_RN##n(s));\n\n#ifndef AV_COPY16U\n#   define AV_COPY16U(d, s) AV_COPYU(16, d, s)\n#endif\n\n#ifndef AV_COPY32U\n#   define AV_COPY32U(d, s) AV_COPYU(32, d, s)\n#endif\n\n#ifndef AV_COPY64U\n#   define AV_COPY64U(d, s) AV_COPYU(64, d, s)\n#endif\n\n#ifndef AV_COPY128U\n#   define AV_COPY128U(d, s)                                    \\\n    do {                                                        \\\n        AV_COPY64U(d, s);                                       \\\n        AV_COPY64U((char *)(d) + 8, (const char *)(s) + 8);     \\\n    } while(0)\n#endif\n\n/* Parameters for AV_COPY*, AV_SWAP*, AV_ZERO* must be\n * naturally aligned. They may be implemented using MMX,\n * so emms_c() must be called before using any float code\n * afterwards.\n */\n\n#define AV_COPY(n, d, s) \\\n    (((av_alias##n*)(d))->u##n = ((const av_alias##n*)(s))->u##n)\n\n#ifndef AV_COPY16\n#   define AV_COPY16(d, s) AV_COPY(16, d, s)\n#endif\n\n#ifndef AV_COPY32\n#   define AV_COPY32(d, s) AV_COPY(32, d, s)\n#endif\n\n#ifndef AV_COPY64\n#   define AV_COPY64(d, s) AV_COPY(64, d, s)\n#endif\n\n#ifndef AV_COPY128\n#   define AV_COPY128(d, s)                    \\\n    do {                                       \\\n        AV_COPY64(d, s);                       \\\n        AV_COPY64((char*)(d)+8, (char*)(s)+8); \\\n    } while(0)\n#endif\n\n#define AV_SWAP(n, a, b) FFSWAP(av_alias##n, *(av_alias##n*)(a), *(av_alias##n*)(b))\n\n#ifndef AV_SWAP64\n#   define AV_SWAP64(a, b) AV_SWAP(64, a, b)\n#endif\n\n#define AV_ZERO(n, d) (((av_alias##n*)(d))->u##n = 0)\n\n#ifndef AV_ZERO16\n#   define AV_ZERO16(d) AV_ZERO(16, d)\n#endif\n\n#ifndef AV_ZERO32\n#   define AV_ZERO32(d) AV_ZERO(32, d)\n#endif\n\n#ifndef AV_ZERO64\n#   define AV_ZERO64(d) AV_ZERO(64, d)\n#endif\n\n#ifndef AV_ZERO128\n#   define AV_ZERO128(d)         \\\n    do {                         \\\n        AV_ZERO64(d);            \\\n        AV_ZERO64((char*)(d)+8); \\\n    } while(0)\n#endif\n\n#endif /* AVUTIL_INTREADWRITE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/lfg.h",
    "content": "/*\n * Lagged Fibonacci PRNG\n * Copyright (c) 2008 Michael Niedermayer\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_LFG_H\n#define AVUTIL_LFG_H\n\n#include <stdint.h>\n\n/**\n * Context structure for the Lagged Fibonacci PRNG.\n * The exact layout, types and content of this struct may change and should\n * not be accessed directly. Only its sizeof() is guranteed to stay the same\n * to allow easy instanciation.\n */\ntypedef struct AVLFG {\n    unsigned int state[64];\n    int index;\n} AVLFG;\n\nvoid av_lfg_init(AVLFG *c, unsigned int seed);\n\n/**\n * Seed the state of the ALFG using binary data.\n *\n * Return value: 0 on success, negative value (AVERROR) on failure.\n */\nint av_lfg_init_from_data(AVLFG *c, const uint8_t *data, unsigned int length);\n\n/**\n * Get the next random unsigned 32-bit number using an ALFG.\n *\n * Please also consider a simple LCG like state= state*1664525+1013904223,\n * it may be good enough and faster for your specific use case.\n */\nstatic inline unsigned int av_lfg_get(AVLFG *c){\n    unsigned a = c->state[c->index & 63] = c->state[(c->index-24) & 63] + c->state[(c->index-55) & 63];\n    c->index += 1U;\n    return a;\n}\n\n/**\n * Get the next random unsigned 32-bit number using a MLFG.\n *\n * Please also consider av_lfg_get() above, it is faster.\n */\nstatic inline unsigned int av_mlfg_get(AVLFG *c){\n    unsigned int a= c->state[(c->index-55) & 63];\n    unsigned int b= c->state[(c->index-24) & 63];\n    a = c->state[c->index & 63] = 2*a*b+a+b;\n    c->index += 1U;\n    return a;\n}\n\n/**\n * Get the next two numbers generated by a Box-Muller Gaussian\n * generator using the random numbers issued by lfg.\n *\n * @param out array where the two generated numbers are placed\n */\nvoid av_bmg_get(AVLFG *lfg, double out[2]);\n\n#endif /* AVUTIL_LFG_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/log.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_LOG_H\n#define AVUTIL_LOG_H\n\n#include <stdarg.h>\n#include \"attributes.h\"\n#include \"version.h\"\n\ntypedef enum {\n    AV_CLASS_CATEGORY_NA = 0,\n    AV_CLASS_CATEGORY_INPUT,\n    AV_CLASS_CATEGORY_OUTPUT,\n    AV_CLASS_CATEGORY_MUXER,\n    AV_CLASS_CATEGORY_DEMUXER,\n    AV_CLASS_CATEGORY_ENCODER,\n    AV_CLASS_CATEGORY_DECODER,\n    AV_CLASS_CATEGORY_FILTER,\n    AV_CLASS_CATEGORY_BITSTREAM_FILTER,\n    AV_CLASS_CATEGORY_SWSCALER,\n    AV_CLASS_CATEGORY_SWRESAMPLER,\n    AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40,\n    AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,\n    AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,\n    AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,\n    AV_CLASS_CATEGORY_DEVICE_OUTPUT,\n    AV_CLASS_CATEGORY_DEVICE_INPUT,\n    AV_CLASS_CATEGORY_NB  ///< not part of ABI/API\n}AVClassCategory;\n\n#define AV_IS_INPUT_DEVICE(category) \\\n    (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) || \\\n     ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) || \\\n     ((category) == AV_CLASS_CATEGORY_DEVICE_INPUT))\n\n#define AV_IS_OUTPUT_DEVICE(category) \\\n    (((category) == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT) || \\\n     ((category) == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) || \\\n     ((category) == AV_CLASS_CATEGORY_DEVICE_OUTPUT))\n\nstruct AVOptionRanges;\n\n/**\n * Describe the class of an AVClass context structure. That is an\n * arbitrary struct of which the first field is a pointer to an\n * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.).\n */\ntypedef struct AVClass {\n    /**\n     * The name of the class; usually it is the same name as the\n     * context structure type to which the AVClass is associated.\n     */\n    const char* class_name;\n\n    /**\n     * A pointer to a function which returns the name of a context\n     * instance ctx associated with the class.\n     */\n    const char* (*item_name)(void* ctx);\n\n    /**\n     * a pointer to the first option specified in the class if any or NULL\n     *\n     * @see av_set_default_options()\n     */\n    const struct AVOption *option;\n\n    /**\n     * LIBAVUTIL_VERSION with which this structure was created.\n     * This is used to allow fields to be added without requiring major\n     * version bumps everywhere.\n     */\n\n    int version;\n\n    /**\n     * Offset in the structure where log_level_offset is stored.\n     * 0 means there is no such variable\n     */\n    int log_level_offset_offset;\n\n    /**\n     * Offset in the structure where a pointer to the parent context for\n     * logging is stored. For example a decoder could pass its AVCodecContext\n     * to eval as such a parent context, which an av_log() implementation\n     * could then leverage to display the parent context.\n     * The offset can be NULL.\n     */\n    int parent_log_context_offset;\n\n    /**\n     * Category used for visualization (like color)\n     * This is only set if the category is equal for all objects using this class.\n     * available since version (51 << 16 | 56 << 8 | 100)\n     */\n    AVClassCategory category;\n\n    /**\n     * Callback to return the category.\n     * available since version (51 << 16 | 59 << 8 | 100)\n     */\n    AVClassCategory (*get_category)(void* ctx);\n\n    /**\n     * Callback to return the supported/allowed ranges.\n     * available since version (52.12)\n     */\n    int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags);\n\n    /**\n     * Return next AVOptions-enabled child or NULL\n     */\n    void* (*child_next)(void *obj, void *prev);\n\n    /**\n     * Iterate over the AVClasses corresponding to potential AVOptions-enabled\n     * children.\n     *\n     * @param iter pointer to opaque iteration state. The caller must initialize\n     *             *iter to NULL before the first call.\n     * @return AVClass for the next AVOptions-enabled child or NULL if there are\n     *         no more such children.\n     *\n     * @note The difference between child_next and this is that child_next\n     *       iterates over _already existing_ objects, while child_class_iterate\n     *       iterates over _all possible_ children.\n     */\n    const struct AVClass* (*child_class_iterate)(void **iter);\n} AVClass;\n\n/**\n * @addtogroup lavu_log\n *\n * @{\n *\n * @defgroup lavu_log_constants Logging Constants\n *\n * @{\n */\n\n/**\n * Print no output.\n */\n#define AV_LOG_QUIET    -8\n\n/**\n * Something went really wrong and we will crash now.\n */\n#define AV_LOG_PANIC     0\n\n/**\n * Something went wrong and recovery is not possible.\n * For example, no header was found for a format which depends\n * on headers or an illegal combination of parameters is used.\n */\n#define AV_LOG_FATAL     8\n\n/**\n * Something went wrong and cannot losslessly be recovered.\n * However, not all future data is affected.\n */\n#define AV_LOG_ERROR    16\n\n/**\n * Something somehow does not look correct. This may or may not\n * lead to problems. An example would be the use of '-vstrict -2'.\n */\n#define AV_LOG_WARNING  24\n\n/**\n * Standard information.\n */\n#define AV_LOG_INFO     32\n\n/**\n * Detailed information.\n */\n#define AV_LOG_VERBOSE  40\n\n/**\n * Stuff which is only useful for libav* developers.\n */\n#define AV_LOG_DEBUG    48\n\n/**\n * Extremely verbose debugging, useful for libav* development.\n */\n#define AV_LOG_TRACE    56\n\n#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET)\n\n/**\n * @}\n */\n\n/**\n * Sets additional colors for extended debugging sessions.\n * @code\n   av_log(ctx, AV_LOG_DEBUG|AV_LOG_C(134), \"Message in purple\\n\");\n   @endcode\n * Requires 256color terminal support. Uses outside debugging is not\n * recommended.\n */\n#define AV_LOG_C(x) ((x) << 8)\n\n/**\n * Send the specified message to the log if the level is less than or equal\n * to the current av_log_level. By default, all logging messages are sent to\n * stderr. This behavior can be altered by setting a different logging callback\n * function.\n * @see av_log_set_callback\n *\n * @param avcl A pointer to an arbitrary struct of which the first field is a\n *        pointer to an AVClass struct or NULL if general log.\n * @param level The importance level of the message expressed using a @ref\n *        lavu_log_constants \"Logging Constant\".\n * @param fmt The format string (printf-compatible) that specifies how\n *        subsequent arguments are converted to output.\n */\nvoid av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4);\n\n/**\n * Send the specified message to the log once with the initial_level and then with\n * the subsequent_level. By default, all logging messages are sent to\n * stderr. This behavior can be altered by setting a different logging callback\n * function.\n * @see av_log\n *\n * @param avcl A pointer to an arbitrary struct of which the first field is a\n *        pointer to an AVClass struct or NULL if general log.\n * @param initial_level importance level of the message expressed using a @ref\n *        lavu_log_constants \"Logging Constant\" for the first occurance.\n * @param subsequent_level importance level of the message expressed using a @ref\n *        lavu_log_constants \"Logging Constant\" after the first occurance.\n * @param fmt The format string (printf-compatible) that specifies how\n *        subsequent arguments are converted to output.\n * @param state a variable to keep trak of if a message has already been printed\n *        this must be initialized to 0 before the first use. The same state\n *        must not be accessed by 2 Threads simultaneously.\n */\nvoid av_log_once(void* avcl, int initial_level, int subsequent_level, int *state, const char *fmt, ...) av_printf_format(5, 6);\n\n\n/**\n * Send the specified message to the log if the level is less than or equal\n * to the current av_log_level. By default, all logging messages are sent to\n * stderr. This behavior can be altered by setting a different logging callback\n * function.\n * @see av_log_set_callback\n *\n * @param avcl A pointer to an arbitrary struct of which the first field is a\n *        pointer to an AVClass struct.\n * @param level The importance level of the message expressed using a @ref\n *        lavu_log_constants \"Logging Constant\".\n * @param fmt The format string (printf-compatible) that specifies how\n *        subsequent arguments are converted to output.\n * @param vl The arguments referenced by the format string.\n */\nvoid av_vlog(void *avcl, int level, const char *fmt, va_list vl);\n\n/**\n * Get the current log level\n *\n * @see lavu_log_constants\n *\n * @return Current log level\n */\nint av_log_get_level(void);\n\n/**\n * Set the log level\n *\n * @see lavu_log_constants\n *\n * @param level Logging level\n */\nvoid av_log_set_level(int level);\n\n/**\n * Set the logging callback\n *\n * @note The callback must be thread safe, even if the application does not use\n *       threads itself as some codecs are multithreaded.\n *\n * @see av_log_default_callback\n *\n * @param callback A logging function with a compatible signature.\n */\nvoid av_log_set_callback(void (*callback)(void*, int, const char*, va_list));\n\n/**\n * Default logging callback\n *\n * It prints the message to stderr, optionally colorizing it.\n *\n * @param avcl A pointer to an arbitrary struct of which the first field is a\n *        pointer to an AVClass struct.\n * @param level The importance level of the message expressed using a @ref\n *        lavu_log_constants \"Logging Constant\".\n * @param fmt The format string (printf-compatible) that specifies how\n *        subsequent arguments are converted to output.\n * @param vl The arguments referenced by the format string.\n */\nvoid av_log_default_callback(void *avcl, int level, const char *fmt,\n                             va_list vl);\n\n/**\n * Return the context name\n *\n * @param  ctx The AVClass context\n *\n * @return The AVClass class_name\n */\nconst char* av_default_item_name(void* ctx);\nAVClassCategory av_default_get_category(void *ptr);\n\n/**\n * Format a line of log the same way as the default callback.\n * @param line          buffer to receive the formatted line\n * @param line_size     size of the buffer\n * @param print_prefix  used to store whether the prefix must be printed;\n *                      must point to a persistent integer initially set to 1\n */\nvoid av_log_format_line(void *ptr, int level, const char *fmt, va_list vl,\n                        char *line, int line_size, int *print_prefix);\n\n/**\n * Format a line of log the same way as the default callback.\n * @param line          buffer to receive the formatted line;\n *                      may be NULL if line_size is 0\n * @param line_size     size of the buffer; at most line_size-1 characters will\n *                      be written to the buffer, plus one null terminator\n * @param print_prefix  used to store whether the prefix must be printed;\n *                      must point to a persistent integer initially set to 1\n * @return Returns a negative value if an error occurred, otherwise returns\n *         the number of characters that would have been written for a\n *         sufficiently large buffer, not including the terminating null\n *         character. If the return value is not less than line_size, it means\n *         that the log message was truncated to fit the buffer.\n */\nint av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl,\n                        char *line, int line_size, int *print_prefix);\n\n/**\n * Skip repeated messages, this requires the user app to use av_log() instead of\n * (f)printf as the 2 would otherwise interfere and lead to\n * \"Last message repeated x times\" messages below (f)printf messages with some\n * bad luck.\n * Also to receive the last, \"last repeated\" line if any, the user app must\n * call av_log(NULL, AV_LOG_QUIET, \"%s\", \"\"); at the end\n */\n#define AV_LOG_SKIP_REPEATED 1\n\n/**\n * Include the log severity in messages originating from codecs.\n *\n * Results in messages such as:\n * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts\n */\n#define AV_LOG_PRINT_LEVEL 2\n\nvoid av_log_set_flags(int arg);\nint av_log_get_flags(void);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_LOG_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/lzo.h",
    "content": "/*\n * LZO 1x decompression\n * copyright (c) 2006 Reimar Doeffinger\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_LZO_H\n#define AVUTIL_LZO_H\n\n/**\n * @defgroup lavu_lzo LZO\n * @ingroup lavu_crypto\n *\n * @{\n */\n\n#include <stdint.h>\n\n/** @name Error flags returned by av_lzo1x_decode\n * @{ */\n/// end of the input buffer reached before decoding finished\n#define AV_LZO_INPUT_DEPLETED  1\n/// decoded data did not fit into output buffer\n#define AV_LZO_OUTPUT_FULL     2\n/// a reference to previously decoded data was wrong\n#define AV_LZO_INVALID_BACKPTR 4\n/// a non-specific error in the compressed bitstream\n#define AV_LZO_ERROR           8\n/** @} */\n\n#define AV_LZO_INPUT_PADDING   8\n#define AV_LZO_OUTPUT_PADDING 12\n\n/**\n * @brief Decodes LZO 1x compressed data.\n * @param out output buffer\n * @param outlen size of output buffer, number of bytes left are returned here\n * @param in input buffer\n * @param inlen size of input buffer, number of bytes left are returned here\n * @return 0 on success, otherwise a combination of the error flags above\n *\n * Make sure all buffers are appropriately padded, in must provide\n * AV_LZO_INPUT_PADDING, out must provide AV_LZO_OUTPUT_PADDING additional bytes.\n */\nint av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_LZO_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/macros.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu\n * Utility Preprocessor macros\n */\n\n#ifndef AVUTIL_MACROS_H\n#define AVUTIL_MACROS_H\n\n#include \"libavutil/avconfig.h\"\n\n#if AV_HAVE_BIGENDIAN\n#   define AV_NE(be, le) (be)\n#else\n#   define AV_NE(be, le) (le)\n#endif\n\n/**\n * Comparator.\n * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0\n * if x == y. This is useful for instance in a qsort comparator callback.\n * Furthermore, compilers are able to optimize this to branchless code, and\n * there is no risk of overflow with signed types.\n * As with many macros, this evaluates its argument multiple times, it thus\n * must not have a side-effect.\n */\n#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y)))\n\n#define FFMAX(a,b) ((a) > (b) ? (a) : (b))\n#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)\n#define FFMIN(a,b) ((a) > (b) ? (b) : (a))\n#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)\n\n#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)\n#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))\n\n#define MKTAG(a,b,c,d)   ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))\n#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24))\n\n/**\n * @addtogroup preproc_misc Preprocessor String Macros\n *\n * String manipulation macros\n *\n * @{\n */\n\n#define AV_STRINGIFY(s)         AV_TOSTRING(s)\n#define AV_TOSTRING(s) #s\n\n#define AV_GLUE(a, b) a ## b\n#define AV_JOIN(a, b) AV_GLUE(a, b)\n\n/**\n * @}\n */\n\n#define AV_PRAGMA(s) _Pragma(#s)\n\n#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1))\n\n#endif /* AVUTIL_MACROS_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/mastering_display_metadata.h",
    "content": "/*\n * Copyright (c) 2016 Neil Birkbeck <neil.birkbeck@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_MASTERING_DISPLAY_METADATA_H\n#define AVUTIL_MASTERING_DISPLAY_METADATA_H\n\n#include \"frame.h\"\n#include \"rational.h\"\n\n\n/**\n * Mastering display metadata capable of representing the color volume of\n * the display used to master the content (SMPTE 2086:2014).\n *\n * To be used as payload of a AVFrameSideData or AVPacketSideData with the\n * appropriate type.\n *\n * @note The struct should be allocated with av_mastering_display_metadata_alloc()\n *       and its size is not a part of the public ABI.\n */\ntypedef struct AVMasteringDisplayMetadata {\n    /**\n     * CIE 1931 xy chromaticity coords of color primaries (r, g, b order).\n     */\n    AVRational display_primaries[3][2];\n\n    /**\n     * CIE 1931 xy chromaticity coords of white point.\n     */\n    AVRational white_point[2];\n\n    /**\n     * Min luminance of mastering display (cd/m^2).\n     */\n    AVRational min_luminance;\n\n    /**\n     * Max luminance of mastering display (cd/m^2).\n     */\n    AVRational max_luminance;\n\n    /**\n     * Flag indicating whether the display primaries (and white point) are set.\n     */\n    int has_primaries;\n\n    /**\n     * Flag indicating whether the luminance (min_ and max_) have been set.\n     */\n    int has_luminance;\n\n} AVMasteringDisplayMetadata;\n\n/**\n * Allocate an AVMasteringDisplayMetadata structure and set its fields to\n * default values. The resulting struct can be freed using av_freep().\n *\n * @return An AVMasteringDisplayMetadata filled with default values or NULL\n *         on failure.\n */\nAVMasteringDisplayMetadata *av_mastering_display_metadata_alloc(void);\n\n/**\n * Allocate a complete AVMasteringDisplayMetadata and add it to the frame.\n *\n * @param frame The frame which side data is added to.\n *\n * @return The AVMasteringDisplayMetadata structure to be filled by caller.\n */\nAVMasteringDisplayMetadata *av_mastering_display_metadata_create_side_data(AVFrame *frame);\n\n/**\n * Content light level needed by to transmit HDR over HDMI (CTA-861.3).\n *\n * To be used as payload of a AVFrameSideData or AVPacketSideData with the\n * appropriate type.\n *\n * @note The struct should be allocated with av_content_light_metadata_alloc()\n *       and its size is not a part of the public ABI.\n */\ntypedef struct AVContentLightMetadata {\n    /**\n     * Max content light level (cd/m^2).\n     */\n    unsigned MaxCLL;\n\n    /**\n     * Max average light level per frame (cd/m^2).\n     */\n    unsigned MaxFALL;\n} AVContentLightMetadata;\n\n/**\n * Allocate an AVContentLightMetadata structure and set its fields to\n * default values. The resulting struct can be freed using av_freep().\n *\n * @return An AVContentLightMetadata filled with default values or NULL\n *         on failure.\n */\nAVContentLightMetadata *av_content_light_metadata_alloc(size_t *size);\n\n/**\n * Allocate a complete AVContentLightMetadata and add it to the frame.\n *\n * @param frame The frame which side data is added to.\n *\n * @return The AVContentLightMetadata structure to be filled by caller.\n */\nAVContentLightMetadata *av_content_light_metadata_create_side_data(AVFrame *frame);\n\n#endif /* AVUTIL_MASTERING_DISPLAY_METADATA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/mathematics.h",
    "content": "/*\n * copyright (c) 2005-2012 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @addtogroup lavu_math\n * Mathematical utilities for working with timestamp and time base.\n */\n\n#ifndef AVUTIL_MATHEMATICS_H\n#define AVUTIL_MATHEMATICS_H\n\n#include <stdint.h>\n#include <math.h>\n#include \"attributes.h\"\n#include \"rational.h\"\n#include \"intfloat.h\"\n\n#ifndef M_E\n#define M_E            2.7182818284590452354   /* e */\n#endif\n#ifndef M_LN2\n#define M_LN2          0.69314718055994530942  /* log_e 2 */\n#endif\n#ifndef M_LN10\n#define M_LN10         2.30258509299404568402  /* log_e 10 */\n#endif\n#ifndef M_LOG2_10\n#define M_LOG2_10      3.32192809488736234787  /* log_2 10 */\n#endif\n#ifndef M_PHI\n#define M_PHI          1.61803398874989484820   /* phi / golden ratio */\n#endif\n#ifndef M_PI\n#define M_PI           3.14159265358979323846  /* pi */\n#endif\n#ifndef M_PI_2\n#define M_PI_2         1.57079632679489661923  /* pi/2 */\n#endif\n#ifndef M_SQRT1_2\n#define M_SQRT1_2      0.70710678118654752440  /* 1/sqrt(2) */\n#endif\n#ifndef M_SQRT2\n#define M_SQRT2        1.41421356237309504880  /* sqrt(2) */\n#endif\n#ifndef NAN\n#define NAN            av_int2float(0x7fc00000)\n#endif\n#ifndef INFINITY\n#define INFINITY       av_int2float(0x7f800000)\n#endif\n\n/**\n * @addtogroup lavu_math\n *\n * @{\n */\n\n/**\n * Rounding methods.\n */\nenum AVRounding {\n    AV_ROUND_ZERO     = 0, ///< Round toward zero.\n    AV_ROUND_INF      = 1, ///< Round away from zero.\n    AV_ROUND_DOWN     = 2, ///< Round toward -infinity.\n    AV_ROUND_UP       = 3, ///< Round toward +infinity.\n    AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero.\n    /**\n     * Flag telling rescaling functions to pass `INT64_MIN`/`MAX` through\n     * unchanged, avoiding special cases for #AV_NOPTS_VALUE.\n     *\n     * Unlike other values of the enumeration AVRounding, this value is a\n     * bitmask that must be used in conjunction with another value of the\n     * enumeration through a bitwise OR, in order to set behavior for normal\n     * cases.\n     *\n     * @code{.c}\n     * av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX);\n     * // Rescaling 3:\n     * //     Calculating 3 * 1 / 2\n     * //     3 / 2 is rounded up to 2\n     * //     => 2\n     *\n     * av_rescale_rnd(AV_NOPTS_VALUE, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX);\n     * // Rescaling AV_NOPTS_VALUE:\n     * //     AV_NOPTS_VALUE == INT64_MIN\n     * //     AV_NOPTS_VALUE is passed through\n     * //     => AV_NOPTS_VALUE\n     * @endcode\n     */\n    AV_ROUND_PASS_MINMAX = 8192,\n};\n\n/**\n * Compute the greatest common divisor of two integer operands.\n *\n * @param a,b Operands\n * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0;\n * if a == 0 and b == 0, returns 0.\n */\nint64_t av_const av_gcd(int64_t a, int64_t b);\n\n/**\n * Rescale a 64-bit integer with rounding to nearest.\n *\n * The operation is mathematically equivalent to `a * b / c`, but writing that\n * directly can overflow.\n *\n * This function is equivalent to av_rescale_rnd() with #AV_ROUND_NEAR_INF.\n *\n * @see av_rescale_rnd(), av_rescale_q(), av_rescale_q_rnd()\n */\nint64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const;\n\n/**\n * Rescale a 64-bit integer with specified rounding.\n *\n * The operation is mathematically equivalent to `a * b / c`, but writing that\n * directly can overflow, and does not support different rounding methods.\n * If the result is not representable then INT64_MIN is returned.\n *\n * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd()\n */\nint64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) av_const;\n\n/**\n * Rescale a 64-bit integer by 2 rational numbers.\n *\n * The operation is mathematically equivalent to `a * bq / cq`.\n *\n * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF.\n *\n * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd()\n */\nint64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;\n\n/**\n * Rescale a 64-bit integer by 2 rational numbers with specified rounding.\n *\n * The operation is mathematically equivalent to `a * bq / cq`.\n *\n * @see av_rescale(), av_rescale_rnd(), av_rescale_q()\n */\nint64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq,\n                         enum AVRounding rnd) av_const;\n\n/**\n * Compare two timestamps each in its own time base.\n *\n * @return One of the following values:\n *         - -1 if `ts_a` is before `ts_b`\n *         - 1 if `ts_a` is after `ts_b`\n *         - 0 if they represent the same position\n *\n * @warning\n * The result of the function is undefined if one of the timestamps is outside\n * the `int64_t` range when represented in the other's timebase.\n */\nint av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b);\n\n/**\n * Compare the remainders of two integer operands divided by a common divisor.\n *\n * In other words, compare the least significant `log2(mod)` bits of integers\n * `a` and `b`.\n *\n * @code{.c}\n * av_compare_mod(0x11, 0x02, 0x10) < 0 // since 0x11 % 0x10  (0x1) < 0x02 % 0x10  (0x2)\n * av_compare_mod(0x11, 0x02, 0x20) > 0 // since 0x11 % 0x20 (0x11) > 0x02 % 0x20 (0x02)\n * @endcode\n *\n * @param a,b Operands\n * @param mod Divisor; must be a power of 2\n * @return\n *         - a negative value if `a % mod < b % mod`\n *         - a positive value if `a % mod > b % mod`\n *         - zero             if `a % mod == b % mod`\n */\nint64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod);\n\n/**\n * Rescale a timestamp while preserving known durations.\n *\n * This function is designed to be called per audio packet to scale the input\n * timestamp to a different time base. Compared to a simple av_rescale_q()\n * call, this function is robust against possible inconsistent frame durations.\n *\n * The `last` parameter is a state variable that must be preserved for all\n * subsequent calls for the same stream. For the first call, `*last` should be\n * initialized to #AV_NOPTS_VALUE.\n *\n * @param[in]     in_tb    Input time base\n * @param[in]     in_ts    Input timestamp\n * @param[in]     fs_tb    Duration time base; typically this is finer-grained\n *                         (greater) than `in_tb` and `out_tb`\n * @param[in]     duration Duration till the next call to this function (i.e.\n *                         duration of the current packet/frame)\n * @param[in,out] last     Pointer to a timestamp expressed in terms of\n *                         `fs_tb`, acting as a state variable\n * @param[in]     out_tb   Output timebase\n * @return        Timestamp expressed in terms of `out_tb`\n *\n * @note In the context of this function, \"duration\" is in term of samples, not\n *       seconds.\n */\nint64_t av_rescale_delta(AVRational in_tb, int64_t in_ts,  AVRational fs_tb, int duration, int64_t *last, AVRational out_tb);\n\n/**\n * Add a value to a timestamp.\n *\n * This function guarantees that when the same value is repeatly added that\n * no accumulation of rounding errors occurs.\n *\n * @param[in] ts     Input timestamp\n * @param[in] ts_tb  Input timestamp time base\n * @param[in] inc    Value to be added\n * @param[in] inc_tb Time base of `inc`\n */\nint64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc);\n\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_MATHEMATICS_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/md5.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_md5\n * Public header for MD5 hash function implementation.\n */\n\n#ifndef AVUTIL_MD5_H\n#define AVUTIL_MD5_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"attributes.h\"\n\n/**\n * @defgroup lavu_md5 MD5\n * @ingroup lavu_hash\n * MD5 hash function implementation.\n *\n * @{\n */\n\nextern const int av_md5_size;\n\nstruct AVMD5;\n\n/**\n * Allocate an AVMD5 context.\n */\nstruct AVMD5 *av_md5_alloc(void);\n\n/**\n * Initialize MD5 hashing.\n *\n * @param ctx pointer to the function context (of size av_md5_size)\n */\nvoid av_md5_init(struct AVMD5 *ctx);\n\n/**\n * Update hash value.\n *\n * @param ctx hash function context\n * @param src input data to update hash with\n * @param len input data length\n */\nvoid av_md5_update(struct AVMD5 *ctx, const uint8_t *src, size_t len);\n\n/**\n * Finish hashing and output digest value.\n *\n * @param ctx hash function context\n * @param dst buffer where output digest value is stored\n */\nvoid av_md5_final(struct AVMD5 *ctx, uint8_t *dst);\n\n/**\n * Hash an array of data.\n *\n * @param dst The output buffer to write the digest into\n * @param src The data to hash\n * @param len The length of the data, in bytes\n */\nvoid av_md5_sum(uint8_t *dst, const uint8_t *src, size_t len);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_MD5_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/mem.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_mem\n * Memory handling functions\n */\n\n#ifndef AVUTIL_MEM_H\n#define AVUTIL_MEM_H\n\n#include <limits.h>\n#include <stdint.h>\n\n#include \"attributes.h\"\n#include \"avutil.h\"\n#include \"version.h\"\n\n/**\n * @addtogroup lavu_mem\n * Utilities for manipulating memory.\n *\n * FFmpeg has several applications of memory that are not required of a typical\n * program. For example, the computing-heavy components like video decoding and\n * encoding can be sped up significantly through the use of aligned memory.\n *\n * However, for each of FFmpeg's applications of memory, there might not be a\n * recognized or standardized API for that specific use. Memory alignment, for\n * instance, varies wildly depending on operating systems, architectures, and\n * compilers. Hence, this component of @ref libavutil is created to make\n * dealing with memory consistently possible on all platforms.\n *\n * @{\n */\n\n#if FF_API_DECLARE_ALIGNED\n/**\n *\n * @defgroup lavu_mem_macros Alignment Macros\n * Helper macros for declaring aligned variables.\n * @{\n */\n\n/**\n * @def DECLARE_ALIGNED(n,t,v)\n * Declare a variable that is aligned in memory.\n *\n * @code{.c}\n * DECLARE_ALIGNED(16, uint16_t, aligned_int) = 42;\n * DECLARE_ALIGNED(32, uint8_t, aligned_array)[128];\n *\n * // The default-alignment equivalent would be\n * uint16_t aligned_int = 42;\n * uint8_t aligned_array[128];\n * @endcode\n *\n * @param n Minimum alignment in bytes\n * @param t Type of the variable (or array element)\n * @param v Name of the variable\n */\n\n/**\n * @def DECLARE_ASM_ALIGNED(n,t,v)\n * Declare an aligned variable appropriate for use in inline assembly code.\n *\n * @code{.c}\n * DECLARE_ASM_ALIGNED(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008);\n * @endcode\n *\n * @param n Minimum alignment in bytes\n * @param t Type of the variable (or array element)\n * @param v Name of the variable\n */\n\n/**\n * @def DECLARE_ASM_CONST(n,t,v)\n * Declare a static constant aligned variable appropriate for use in inline\n * assembly code.\n *\n * @code{.c}\n * DECLARE_ASM_CONST(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008);\n * @endcode\n *\n * @param n Minimum alignment in bytes\n * @param t Type of the variable (or array element)\n * @param v Name of the variable\n */\n\n#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C)\n    #define DECLARE_ALIGNED(n,t,v)      t __attribute__ ((aligned (n))) v\n    #define DECLARE_ASM_ALIGNED(n,t,v)  t __attribute__ ((aligned (n))) v\n    #define DECLARE_ASM_CONST(n,t,v)    const t __attribute__ ((aligned (n))) v\n#elif defined(__DJGPP__)\n    #define DECLARE_ALIGNED(n,t,v)      t __attribute__ ((aligned (FFMIN(n, 16)))) v\n    #define DECLARE_ASM_ALIGNED(n,t,v)  t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v\n    #define DECLARE_ASM_CONST(n,t,v)    static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v\n#elif defined(__GNUC__) || defined(__clang__)\n    #define DECLARE_ALIGNED(n,t,v)      t __attribute__ ((aligned (n))) v\n    #define DECLARE_ASM_ALIGNED(n,t,v)  t av_used __attribute__ ((aligned (n))) v\n    #define DECLARE_ASM_CONST(n,t,v)    static const t av_used __attribute__ ((aligned (n))) v\n#elif defined(_MSC_VER)\n    #define DECLARE_ALIGNED(n,t,v)      __declspec(align(n)) t v\n    #define DECLARE_ASM_ALIGNED(n,t,v)  __declspec(align(n)) t v\n    #define DECLARE_ASM_CONST(n,t,v)    __declspec(align(n)) static const t v\n#else\n    #define DECLARE_ALIGNED(n,t,v)      t v\n    #define DECLARE_ASM_ALIGNED(n,t,v)  t v\n    #define DECLARE_ASM_CONST(n,t,v)    static const t v\n#endif\n\n/**\n * @}\n */\n#endif\n\n/**\n * @defgroup lavu_mem_attrs Function Attributes\n * Function attributes applicable to memory handling functions.\n *\n * These function attributes can help compilers emit more useful warnings, or\n * generate better code.\n * @{\n */\n\n/**\n * @def av_malloc_attrib\n * Function attribute denoting a malloc-like function.\n *\n * @see <a href=\"https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007bmalloc_007d-function-attribute-3251\">Function attribute `malloc` in GCC's documentation</a>\n */\n\n#if AV_GCC_VERSION_AT_LEAST(3,1)\n    #define av_malloc_attrib __attribute__((__malloc__))\n#else\n    #define av_malloc_attrib\n#endif\n\n/**\n * @def av_alloc_size(...)\n * Function attribute used on a function that allocates memory, whose size is\n * given by the specified parameter(s).\n *\n * @code{.c}\n * void *av_malloc(size_t size) av_alloc_size(1);\n * void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2);\n * @endcode\n *\n * @param ... One or two parameter indexes, separated by a comma\n *\n * @see <a href=\"https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007balloc_005fsize_007d-function-attribute-3220\">Function attribute `alloc_size` in GCC's documentation</a>\n */\n\n#if AV_GCC_VERSION_AT_LEAST(4,3)\n    #define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__)))\n#else\n    #define av_alloc_size(...)\n#endif\n\n/**\n * @}\n */\n\n/**\n * @defgroup lavu_mem_funcs Heap Management\n * Functions responsible for allocating, freeing, and copying memory.\n *\n * All memory allocation functions have a built-in upper limit of `INT_MAX`\n * bytes. This may be changed with av_max_alloc(), although exercise extreme\n * caution when doing so.\n *\n * @{\n */\n\n/**\n * Allocate a memory block with alignment suitable for all memory accesses\n * (including vectors if available on the CPU).\n *\n * @param size Size in bytes for the memory block to be allocated\n * @return Pointer to the allocated block, or `NULL` if the block cannot\n *         be allocated\n * @see av_mallocz()\n */\nvoid *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1);\n\n/**\n * Allocate a memory block with alignment suitable for all memory accesses\n * (including vectors if available on the CPU) and zero all the bytes of the\n * block.\n *\n * @param size Size in bytes for the memory block to be allocated\n * @return Pointer to the allocated block, or `NULL` if it cannot be allocated\n * @see av_malloc()\n */\nvoid *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1);\n\n/**\n * Allocate a memory block for an array with av_malloc().\n *\n * The allocated memory will have size `size * nmemb` bytes.\n *\n * @param nmemb Number of element\n * @param size  Size of a single element\n * @return Pointer to the allocated block, or `NULL` if the block cannot\n *         be allocated\n * @see av_malloc()\n */\nav_alloc_size(1, 2) void *av_malloc_array(size_t nmemb, size_t size);\n\n/**\n * Allocate a memory block for an array with av_mallocz().\n *\n * The allocated memory will have size `size * nmemb` bytes.\n *\n * @param nmemb Number of elements\n * @param size  Size of the single element\n * @return Pointer to the allocated block, or `NULL` if the block cannot\n *         be allocated\n *\n * @see av_mallocz()\n * @see av_malloc_array()\n */\nvoid *av_calloc(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2);\n\n#if FF_API_AV_MALLOCZ_ARRAY\n/**\n * @deprecated use av_calloc()\n */\nattribute_deprecated\nvoid *av_mallocz_array(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size(1, 2);\n#endif\n\n/**\n * Allocate, reallocate, or free a block of memory.\n *\n * If `ptr` is `NULL` and `size` > 0, allocate a new block. Otherwise, expand or\n * shrink that block of memory according to `size`.\n *\n * @param ptr  Pointer to a memory block already allocated with\n *             av_realloc() or `NULL`\n * @param size Size in bytes of the memory block to be allocated or\n *             reallocated\n *\n * @return Pointer to a newly-reallocated block or `NULL` if the block\n *         cannot be reallocated\n *\n * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be\n *          correctly aligned. The returned pointer must be freed after even\n *          if size is zero.\n * @see av_fast_realloc()\n * @see av_reallocp()\n */\nvoid *av_realloc(void *ptr, size_t size) av_alloc_size(2);\n\n/**\n * Allocate, reallocate, or free a block of memory through a pointer to a\n * pointer.\n *\n * If `*ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is\n * zero, free the memory block pointed to by `*ptr`. Otherwise, expand or\n * shrink that block of memory according to `size`.\n *\n * @param[in,out] ptr  Pointer to a pointer to a memory block already allocated\n *                     with av_realloc(), or a pointer to `NULL`. The pointer\n *                     is updated on success, or freed on failure.\n * @param[in]     size Size in bytes for the memory block to be allocated or\n *                     reallocated\n *\n * @return Zero on success, an AVERROR error code on failure\n *\n * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be\n *          correctly aligned.\n */\nav_warn_unused_result\nint av_reallocp(void *ptr, size_t size);\n\n/**\n * Allocate, reallocate, or free a block of memory.\n *\n * This function does the same thing as av_realloc(), except:\n * - It takes two size arguments and allocates `nelem * elsize` bytes,\n *   after checking the result of the multiplication for integer overflow.\n * - It frees the input block in case of failure, thus avoiding the memory\n *   leak with the classic\n *   @code{.c}\n *   buf = realloc(buf);\n *   if (!buf)\n *       return -1;\n *   @endcode\n *   pattern.\n */\nvoid *av_realloc_f(void *ptr, size_t nelem, size_t elsize);\n\n/**\n * Allocate, reallocate, or free an array.\n *\n * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block.\n *\n * @param ptr   Pointer to a memory block already allocated with\n *              av_realloc() or `NULL`\n * @param nmemb Number of elements in the array\n * @param size  Size of the single element of the array\n *\n * @return Pointer to a newly-reallocated block or NULL if the block\n *         cannot be reallocated\n *\n * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be\n *          correctly aligned. The returned pointer must be freed after even if\n *          nmemb is zero.\n * @see av_reallocp_array()\n */\nav_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size);\n\n/**\n * Allocate, reallocate an array through a pointer to a pointer.\n *\n * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block.\n *\n * @param[in,out] ptr   Pointer to a pointer to a memory block already\n *                      allocated with av_realloc(), or a pointer to `NULL`.\n *                      The pointer is updated on success, or freed on failure.\n * @param[in]     nmemb Number of elements\n * @param[in]     size  Size of the single element\n *\n * @return Zero on success, an AVERROR error code on failure\n *\n * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be\n *          correctly aligned. *ptr must be freed after even if nmemb is zero.\n */\nint av_reallocp_array(void *ptr, size_t nmemb, size_t size);\n\n/**\n * Reallocate the given buffer if it is not large enough, otherwise do nothing.\n *\n * If the given buffer is `NULL`, then a new uninitialized buffer is allocated.\n *\n * If the given buffer is not large enough, and reallocation fails, `NULL` is\n * returned and `*size` is set to 0, but the original buffer is not changed or\n * freed.\n *\n * A typical use pattern follows:\n *\n * @code{.c}\n * uint8_t *buf = ...;\n * uint8_t *new_buf = av_fast_realloc(buf, &current_size, size_needed);\n * if (!new_buf) {\n *     // Allocation failed; clean up original buffer\n *     av_freep(&buf);\n *     return AVERROR(ENOMEM);\n * }\n * @endcode\n *\n * @param[in,out] ptr      Already allocated buffer, or `NULL`\n * @param[in,out] size     Pointer to the size of buffer `ptr`. `*size` is\n *                         updated to the new allocated size, in particular 0\n *                         in case of failure.\n * @param[in]     min_size Desired minimal size of buffer `ptr`\n * @return `ptr` if the buffer is large enough, a pointer to newly reallocated\n *         buffer if the buffer was not large enough, or `NULL` in case of\n *         error\n * @see av_realloc()\n * @see av_fast_malloc()\n */\nvoid *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size);\n\n/**\n * Allocate a buffer, reusing the given one if large enough.\n *\n * Contrary to av_fast_realloc(), the current buffer contents might not be\n * preserved and on error the old buffer is freed, thus no special handling to\n * avoid memleaks is necessary.\n *\n * `*ptr` is allowed to be `NULL`, in which case allocation always happens if\n * `size_needed` is greater than 0.\n *\n * @code{.c}\n * uint8_t *buf = ...;\n * av_fast_malloc(&buf, &current_size, size_needed);\n * if (!buf) {\n *     // Allocation failed; buf already freed\n *     return AVERROR(ENOMEM);\n * }\n * @endcode\n *\n * @param[in,out] ptr      Pointer to pointer to an already allocated buffer.\n *                         `*ptr` will be overwritten with pointer to new\n *                         buffer on success or `NULL` on failure\n * @param[in,out] size     Pointer to the size of buffer `*ptr`. `*size` is\n *                         updated to the new allocated size, in particular 0\n *                         in case of failure.\n * @param[in]     min_size Desired minimal size of buffer `*ptr`\n * @see av_realloc()\n * @see av_fast_mallocz()\n */\nvoid av_fast_malloc(void *ptr, unsigned int *size, size_t min_size);\n\n/**\n * Allocate and clear a buffer, reusing the given one if large enough.\n *\n * Like av_fast_malloc(), but all newly allocated space is initially cleared.\n * Reused buffer is not cleared.\n *\n * `*ptr` is allowed to be `NULL`, in which case allocation always happens if\n * `size_needed` is greater than 0.\n *\n * @param[in,out] ptr      Pointer to pointer to an already allocated buffer.\n *                         `*ptr` will be overwritten with pointer to new\n *                         buffer on success or `NULL` on failure\n * @param[in,out] size     Pointer to the size of buffer `*ptr`. `*size` is\n *                         updated to the new allocated size, in particular 0\n *                         in case of failure.\n * @param[in]     min_size Desired minimal size of buffer `*ptr`\n * @see av_fast_malloc()\n */\nvoid av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size);\n\n/**\n * Free a memory block which has been allocated with a function of av_malloc()\n * or av_realloc() family.\n *\n * @param ptr Pointer to the memory block which should be freed.\n *\n * @note `ptr = NULL` is explicitly allowed.\n * @note It is recommended that you use av_freep() instead, to prevent leaving\n *       behind dangling pointers.\n * @see av_freep()\n */\nvoid av_free(void *ptr);\n\n/**\n * Free a memory block which has been allocated with a function of av_malloc()\n * or av_realloc() family, and set the pointer pointing to it to `NULL`.\n *\n * @code{.c}\n * uint8_t *buf = av_malloc(16);\n * av_free(buf);\n * // buf now contains a dangling pointer to freed memory, and accidental\n * // dereference of buf will result in a use-after-free, which may be a\n * // security risk.\n *\n * uint8_t *buf = av_malloc(16);\n * av_freep(&buf);\n * // buf is now NULL, and accidental dereference will only result in a\n * // NULL-pointer dereference.\n * @endcode\n *\n * @param ptr Pointer to the pointer to the memory block which should be freed\n * @note `*ptr = NULL` is safe and leads to no action.\n * @see av_free()\n */\nvoid av_freep(void *ptr);\n\n/**\n * Duplicate a string.\n *\n * @param s String to be duplicated\n * @return Pointer to a newly-allocated string containing a\n *         copy of `s` or `NULL` if the string cannot be allocated\n * @see av_strndup()\n */\nchar *av_strdup(const char *s) av_malloc_attrib;\n\n/**\n * Duplicate a substring of a string.\n *\n * @param s   String to be duplicated\n * @param len Maximum length of the resulting string (not counting the\n *            terminating byte)\n * @return Pointer to a newly-allocated string containing a\n *         substring of `s` or `NULL` if the string cannot be allocated\n */\nchar *av_strndup(const char *s, size_t len) av_malloc_attrib;\n\n/**\n * Duplicate a buffer with av_malloc().\n *\n * @param p    Buffer to be duplicated\n * @param size Size in bytes of the buffer copied\n * @return Pointer to a newly allocated buffer containing a\n *         copy of `p` or `NULL` if the buffer cannot be allocated\n */\nvoid *av_memdup(const void *p, size_t size);\n\n/**\n * Overlapping memcpy() implementation.\n *\n * @param dst  Destination buffer\n * @param back Number of bytes back to start copying (i.e. the initial size of\n *             the overlapping window); must be > 0\n * @param cnt  Number of bytes to copy; must be >= 0\n *\n * @note `cnt > back` is valid, this will copy the bytes we just copied,\n *       thus creating a repeating pattern with a period length of `back`.\n */\nvoid av_memcpy_backptr(uint8_t *dst, int back, int cnt);\n\n/**\n * @}\n */\n\n/**\n * @defgroup lavu_mem_dynarray Dynamic Array\n *\n * Utilities to make an array grow when needed.\n *\n * Sometimes, the programmer would want to have an array that can grow when\n * needed. The libavutil dynamic array utilities fill that need.\n *\n * libavutil supports two systems of appending elements onto a dynamically\n * allocated array, the first one storing the pointer to the value in the\n * array, and the second storing the value directly. In both systems, the\n * caller is responsible for maintaining a variable containing the length of\n * the array, as well as freeing of the array after use.\n *\n * The first system stores pointers to values in a block of dynamically\n * allocated memory. Since only pointers are stored, the function does not need\n * to know the size of the type. Both av_dynarray_add() and\n * av_dynarray_add_nofree() implement this system.\n *\n * @code\n * type **array = NULL; //< an array of pointers to values\n * int    nb    = 0;    //< a variable to keep track of the length of the array\n *\n * type to_be_added  = ...;\n * type to_be_added2 = ...;\n *\n * av_dynarray_add(&array, &nb, &to_be_added);\n * if (nb == 0)\n *     return AVERROR(ENOMEM);\n *\n * av_dynarray_add(&array, &nb, &to_be_added2);\n * if (nb == 0)\n *     return AVERROR(ENOMEM);\n *\n * // Now:\n * //  nb           == 2\n * // &to_be_added  == array[0]\n * // &to_be_added2 == array[1]\n *\n * av_freep(&array);\n * @endcode\n *\n * The second system stores the value directly in a block of memory. As a\n * result, the function has to know the size of the type. av_dynarray2_add()\n * implements this mechanism.\n *\n * @code\n * type *array = NULL; //< an array of values\n * int   nb    = 0;    //< a variable to keep track of the length of the array\n *\n * type to_be_added  = ...;\n * type to_be_added2 = ...;\n *\n * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array), NULL);\n * if (!addr)\n *     return AVERROR(ENOMEM);\n * memcpy(addr, &to_be_added, sizeof(to_be_added));\n *\n * // Shortcut of the above.\n * type *addr = av_dynarray2_add((void **)&array, &nb, sizeof(*array),\n *                               (const void *)&to_be_added2);\n * if (!addr)\n *     return AVERROR(ENOMEM);\n *\n * // Now:\n * //  nb           == 2\n * //  to_be_added  == array[0]\n * //  to_be_added2 == array[1]\n *\n * av_freep(&array);\n * @endcode\n *\n * @{\n */\n\n/**\n * Add the pointer to an element to a dynamic array.\n *\n * The array to grow is supposed to be an array of pointers to\n * structures, and the element to add must be a pointer to an already\n * allocated structure.\n *\n * The array is reallocated when its size reaches powers of 2.\n * Therefore, the amortized cost of adding an element is constant.\n *\n * In case of success, the pointer to the array is updated in order to\n * point to the new grown array, and the number pointed to by `nb_ptr`\n * is incremented.\n * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and\n * `*nb_ptr` is set to 0.\n *\n * @param[in,out] tab_ptr Pointer to the array to grow\n * @param[in,out] nb_ptr  Pointer to the number of elements in the array\n * @param[in]     elem    Element to add\n * @see av_dynarray_add_nofree(), av_dynarray2_add()\n */\nvoid av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem);\n\n/**\n * Add an element to a dynamic array.\n *\n * Function has the same functionality as av_dynarray_add(),\n * but it doesn't free memory on fails. It returns error code\n * instead and leave current buffer untouched.\n *\n * @return >=0 on success, negative otherwise\n * @see av_dynarray_add(), av_dynarray2_add()\n */\nav_warn_unused_result\nint av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem);\n\n/**\n * Add an element of size `elem_size` to a dynamic array.\n *\n * The array is reallocated when its number of elements reaches powers of 2.\n * Therefore, the amortized cost of adding an element is constant.\n *\n * In case of success, the pointer to the array is updated in order to\n * point to the new grown array, and the number pointed to by `nb_ptr`\n * is incremented.\n * In case of failure, the array is freed, `*tab_ptr` is set to `NULL` and\n * `*nb_ptr` is set to 0.\n *\n * @param[in,out] tab_ptr   Pointer to the array to grow\n * @param[in,out] nb_ptr    Pointer to the number of elements in the array\n * @param[in]     elem_size Size in bytes of an element in the array\n * @param[in]     elem_data Pointer to the data of the element to add. If\n *                          `NULL`, the space of the newly added element is\n *                          allocated but left uninitialized.\n *\n * @return Pointer to the data of the element to copy in the newly allocated\n *         space\n * @see av_dynarray_add(), av_dynarray_add_nofree()\n */\nvoid *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,\n                       const uint8_t *elem_data);\n\n/**\n * @}\n */\n\n/**\n * @defgroup lavu_mem_misc Miscellaneous Functions\n *\n * Other functions related to memory allocation.\n *\n * @{\n */\n\n/**\n * Multiply two `size_t` values checking for overflow.\n *\n * @param[in]  a,b Operands of multiplication\n * @param[out] r   Pointer to the result of the operation\n * @return 0 on success, AVERROR(EINVAL) on overflow\n */\nint av_size_mult(size_t a, size_t b, size_t *r);\n\n/**\n * Set the maximum size that may be allocated in one block.\n *\n * The value specified with this function is effective for all libavutil's @ref\n * lavu_mem_funcs \"heap management functions.\"\n *\n * By default, the max value is defined as `INT_MAX`.\n *\n * @param max Value to be set as the new maximum size\n *\n * @warning Exercise extreme caution when using this function. Don't touch\n *          this if you do not understand the full consequence of doing so.\n */\nvoid av_max_alloc(size_t max);\n\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_MEM_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/motion_vector.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_MOTION_VECTOR_H\n#define AVUTIL_MOTION_VECTOR_H\n\n#include <stdint.h>\n\ntypedef struct AVMotionVector {\n    /**\n     * Where the current macroblock comes from; negative value when it comes\n     * from the past, positive value when it comes from the future.\n     * XXX: set exact relative ref frame reference instead of a +/- 1 \"direction\".\n     */\n    int32_t source;\n    /**\n     * Width and height of the block.\n     */\n    uint8_t w, h;\n    /**\n     * Absolute source position. Can be outside the frame area.\n     */\n    int16_t src_x, src_y;\n    /**\n     * Absolute destination position. Can be outside the frame area.\n     */\n    int16_t dst_x, dst_y;\n    /**\n     * Extra flag information.\n     * Currently unused.\n     */\n    uint64_t flags;\n    /**\n     * Motion vector\n     * src_x = dst_x + motion_x / motion_scale\n     * src_y = dst_y + motion_y / motion_scale\n     */\n    int32_t motion_x, motion_y;\n    uint16_t motion_scale;\n} AVMotionVector;\n\n#endif /* AVUTIL_MOTION_VECTOR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/murmur3.h",
    "content": "/*\n * Copyright (C) 2013 Reimar Döffinger <Reimar.Doeffinger@gmx.de>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_murmur3\n * Public header for MurmurHash3 hash function implementation.\n */\n\n#ifndef AVUTIL_MURMUR3_H\n#define AVUTIL_MURMUR3_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * @defgroup lavu_murmur3 Murmur3\n * @ingroup lavu_hash\n * MurmurHash3 hash function implementation.\n *\n * MurmurHash3 is a non-cryptographic hash function, of which three\n * incompatible versions were created by its inventor Austin Appleby:\n *\n * - 32-bit output\n * - 128-bit output for 32-bit platforms\n * - 128-bit output for 64-bit platforms\n *\n * FFmpeg only implements the last variant: 128-bit output designed for 64-bit\n * platforms. Even though the hash function was designed for 64-bit platforms,\n * the function in reality works on 32-bit systems too, only with reduced\n * performance.\n *\n * @anchor lavu_murmur3_seedinfo\n * By design, MurmurHash3 requires a seed to operate. In response to this,\n * libavutil provides two functions for hash initiation, one that requires a\n * seed (av_murmur3_init_seeded()) and one that uses a fixed arbitrary integer\n * as the seed, and therefore does not (av_murmur3_init()).\n *\n * To make hashes comparable, you should provide the same seed for all calls to\n * this hash function -- if you are supplying one yourself, that is.\n *\n * @{\n */\n\n/**\n * Allocate an AVMurMur3 hash context.\n *\n * @return Uninitialized hash context or `NULL` in case of error\n */\nstruct AVMurMur3 *av_murmur3_alloc(void);\n\n/**\n * Initialize or reinitialize an AVMurMur3 hash context with a seed.\n *\n * @param[out] c    Hash context\n * @param[in]  seed Random seed\n *\n * @see av_murmur3_init()\n * @see @ref lavu_murmur3_seedinfo \"Detailed description\" on a discussion of\n * seeds for MurmurHash3.\n */\nvoid av_murmur3_init_seeded(struct AVMurMur3 *c, uint64_t seed);\n\n/**\n * Initialize or reinitialize an AVMurMur3 hash context.\n *\n * Equivalent to av_murmur3_init_seeded() with a built-in seed.\n *\n * @param[out] c    Hash context\n *\n * @see av_murmur3_init_seeded()\n * @see @ref lavu_murmur3_seedinfo \"Detailed description\" on a discussion of\n * seeds for MurmurHash3.\n */\nvoid av_murmur3_init(struct AVMurMur3 *c);\n\n/**\n * Update hash context with new data.\n *\n * @param[out] c    Hash context\n * @param[in]  src  Input data to update hash with\n * @param[in]  len  Number of bytes to read from `src`\n */\nvoid av_murmur3_update(struct AVMurMur3 *c, const uint8_t *src, size_t len);\n\n/**\n * Finish hashing and output digest value.\n *\n * @param[in,out] c    Hash context\n * @param[out]    dst  Buffer where output digest value is stored\n */\nvoid av_murmur3_final(struct AVMurMur3 *c, uint8_t dst[16]);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_MURMUR3_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/opt.h",
    "content": "/*\n * AVOptions\n * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_OPT_H\n#define AVUTIL_OPT_H\n\n/**\n * @file\n * AVOptions\n */\n\n#include \"rational.h\"\n#include \"avutil.h\"\n#include \"channel_layout.h\"\n#include \"dict.h\"\n#include \"log.h\"\n#include \"pixfmt.h\"\n#include \"samplefmt.h\"\n\n/**\n * @defgroup avoptions AVOptions\n * @ingroup lavu_data\n * @{\n * AVOptions provide a generic system to declare options on arbitrary structs\n * (\"objects\"). An option can have a help text, a type and a range of possible\n * values. Options may then be enumerated, read and written to.\n *\n * @section avoptions_implement Implementing AVOptions\n * This section describes how to add AVOptions capabilities to a struct.\n *\n * All AVOptions-related information is stored in an AVClass. Therefore\n * the first member of the struct should be a pointer to an AVClass describing it.\n * The option field of the AVClass must be set to a NULL-terminated static array\n * of AVOptions. Each AVOption must have a non-empty name, a type, a default\n * value and for number-type AVOptions also a range of allowed values. It must\n * also declare an offset in bytes from the start of the struct, where the field\n * associated with this AVOption is located. Other fields in the AVOption struct\n * should also be set when applicable, but are not required.\n *\n * The following example illustrates an AVOptions-enabled struct:\n * @code\n * typedef struct test_struct {\n *     const AVClass *class;\n *     int      int_opt;\n *     char    *str_opt;\n *     uint8_t *bin_opt;\n *     int      bin_len;\n * } test_struct;\n *\n * static const AVOption test_options[] = {\n *   { \"test_int\", \"This is a test option of int type.\", offsetof(test_struct, int_opt),\n *     AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX },\n *   { \"test_str\", \"This is a test option of string type.\", offsetof(test_struct, str_opt),\n *     AV_OPT_TYPE_STRING },\n *   { \"test_bin\", \"This is a test option of binary type.\", offsetof(test_struct, bin_opt),\n *     AV_OPT_TYPE_BINARY },\n *   { NULL },\n * };\n *\n * static const AVClass test_class = {\n *     .class_name = \"test class\",\n *     .item_name  = av_default_item_name,\n *     .option     = test_options,\n *     .version    = LIBAVUTIL_VERSION_INT,\n * };\n * @endcode\n *\n * Next, when allocating your struct, you must ensure that the AVClass pointer\n * is set to the correct value. Then, av_opt_set_defaults() can be called to\n * initialize defaults. After that the struct is ready to be used with the\n * AVOptions API.\n *\n * When cleaning up, you may use the av_opt_free() function to automatically\n * free all the allocated string and binary options.\n *\n * Continuing with the above example:\n *\n * @code\n * test_struct *alloc_test_struct(void)\n * {\n *     test_struct *ret = av_mallocz(sizeof(*ret));\n *     ret->class = &test_class;\n *     av_opt_set_defaults(ret);\n *     return ret;\n * }\n * void free_test_struct(test_struct **foo)\n * {\n *     av_opt_free(*foo);\n *     av_freep(foo);\n * }\n * @endcode\n *\n * @subsection avoptions_implement_nesting Nesting\n *      It may happen that an AVOptions-enabled struct contains another\n *      AVOptions-enabled struct as a member (e.g. AVCodecContext in\n *      libavcodec exports generic options, while its priv_data field exports\n *      codec-specific options). In such a case, it is possible to set up the\n *      parent struct to export a child's options. To do that, simply\n *      implement AVClass.child_next() and AVClass.child_class_iterate() in the\n *      parent struct's AVClass.\n *      Assuming that the test_struct from above now also contains a\n *      child_struct field:\n *\n *      @code\n *      typedef struct child_struct {\n *          AVClass *class;\n *          int flags_opt;\n *      } child_struct;\n *      static const AVOption child_opts[] = {\n *          { \"test_flags\", \"This is a test option of flags type.\",\n *            offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX },\n *          { NULL },\n *      };\n *      static const AVClass child_class = {\n *          .class_name = \"child class\",\n *          .item_name  = av_default_item_name,\n *          .option     = child_opts,\n *          .version    = LIBAVUTIL_VERSION_INT,\n *      };\n *\n *      void *child_next(void *obj, void *prev)\n *      {\n *          test_struct *t = obj;\n *          if (!prev && t->child_struct)\n *              return t->child_struct;\n *          return NULL\n *      }\n *      const AVClass child_class_iterate(void **iter)\n *      {\n *          const AVClass *c = *iter ? NULL : &child_class;\n *          *iter = (void*)(uintptr_t)c;\n *          return c;\n *      }\n *      @endcode\n *      Putting child_next() and child_class_iterate() as defined above into\n *      test_class will now make child_struct's options accessible through\n *      test_struct (again, proper setup as described above needs to be done on\n *      child_struct right after it is created).\n *\n *      From the above example it might not be clear why both child_next()\n *      and child_class_iterate() are needed. The distinction is that child_next()\n *      iterates over actually existing objects, while child_class_iterate()\n *      iterates over all possible child classes. E.g. if an AVCodecContext\n *      was initialized to use a codec which has private options, then its\n *      child_next() will return AVCodecContext.priv_data and finish\n *      iterating. OTOH child_class_iterate() on AVCodecContext.av_class will\n *      iterate over all available codecs with private options.\n *\n * @subsection avoptions_implement_named_constants Named constants\n *      It is possible to create named constants for options. Simply set the unit\n *      field of the option the constants should apply to a string and\n *      create the constants themselves as options of type AV_OPT_TYPE_CONST\n *      with their unit field set to the same string.\n *      Their default_val field should contain the value of the named\n *      constant.\n *      For example, to add some named constants for the test_flags option\n *      above, put the following into the child_opts array:\n *      @code\n *      { \"test_flags\", \"This is a test option of flags type.\",\n *        offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, \"test_unit\" },\n *      { \"flag1\", \"This is a flag with value 16\", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, \"test_unit\" },\n *      @endcode\n *\n * @section avoptions_use Using AVOptions\n * This section deals with accessing options in an AVOptions-enabled struct.\n * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or\n * AVFormatContext in libavformat.\n *\n * @subsection avoptions_use_examine Examining AVOptions\n * The basic functions for examining options are av_opt_next(), which iterates\n * over all options defined for one object, and av_opt_find(), which searches\n * for an option with the given name.\n *\n * The situation is more complicated with nesting. An AVOptions-enabled struct\n * may have AVOptions-enabled children. Passing the AV_OPT_SEARCH_CHILDREN flag\n * to av_opt_find() will make the function search children recursively.\n *\n * For enumerating there are basically two cases. The first is when you want to\n * get all options that may potentially exist on the struct and its children\n * (e.g.  when constructing documentation). In that case you should call\n * av_opt_child_class_iterate() recursively on the parent struct's AVClass.  The\n * second case is when you have an already initialized struct with all its\n * children and you want to get all options that can be actually written or read\n * from it. In that case you should call av_opt_child_next() recursively (and\n * av_opt_next() on each result).\n *\n * @subsection avoptions_use_get_set Reading and writing AVOptions\n * When setting options, you often have a string read directly from the\n * user. In such a case, simply passing it to av_opt_set() is enough. For\n * non-string type options, av_opt_set() will parse the string according to the\n * option type.\n *\n * Similarly av_opt_get() will read any option type and convert it to a string\n * which will be returned. Do not forget that the string is allocated, so you\n * have to free it with av_free().\n *\n * In some cases it may be more convenient to put all options into an\n * AVDictionary and call av_opt_set_dict() on it. A specific case of this\n * are the format/codec open functions in lavf/lavc which take a dictionary\n * filled with option as a parameter. This makes it possible to set some options\n * that cannot be set otherwise, since e.g. the input file format is not known\n * before the file is actually opened.\n */\n\nenum AVOptionType{\n    AV_OPT_TYPE_FLAGS,\n    AV_OPT_TYPE_INT,\n    AV_OPT_TYPE_INT64,\n    AV_OPT_TYPE_DOUBLE,\n    AV_OPT_TYPE_FLOAT,\n    AV_OPT_TYPE_STRING,\n    AV_OPT_TYPE_RATIONAL,\n    AV_OPT_TYPE_BINARY,  ///< offset must point to a pointer immediately followed by an int for the length\n    AV_OPT_TYPE_DICT,\n    AV_OPT_TYPE_UINT64,\n    AV_OPT_TYPE_CONST,\n    AV_OPT_TYPE_IMAGE_SIZE, ///< offset must point to two consecutive integers\n    AV_OPT_TYPE_PIXEL_FMT,\n    AV_OPT_TYPE_SAMPLE_FMT,\n    AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational\n    AV_OPT_TYPE_DURATION,\n    AV_OPT_TYPE_COLOR,\n#if FF_API_OLD_CHANNEL_LAYOUT\n    AV_OPT_TYPE_CHANNEL_LAYOUT,\n#endif\n    AV_OPT_TYPE_BOOL,\n    AV_OPT_TYPE_CHLAYOUT,\n};\n\n/**\n * AVOption\n */\ntypedef struct AVOption {\n    const char *name;\n\n    /**\n     * short English help text\n     * @todo What about other languages?\n     */\n    const char *help;\n\n    /**\n     * The offset relative to the context structure where the option\n     * value is stored. It should be 0 for named constants.\n     */\n    int offset;\n    enum AVOptionType type;\n\n    /**\n     * the default value for scalar options\n     */\n    union {\n        int64_t i64;\n        double dbl;\n        const char *str;\n        /* TODO those are unused now */\n        AVRational q;\n    } default_val;\n    double min;                 ///< minimum valid value for the option\n    double max;                 ///< maximum valid value for the option\n\n    int flags;\n#define AV_OPT_FLAG_ENCODING_PARAM  1   ///< a generic parameter which can be set by the user for muxing or encoding\n#define AV_OPT_FLAG_DECODING_PARAM  2   ///< a generic parameter which can be set by the user for demuxing or decoding\n#define AV_OPT_FLAG_AUDIO_PARAM     8\n#define AV_OPT_FLAG_VIDEO_PARAM     16\n#define AV_OPT_FLAG_SUBTITLE_PARAM  32\n/**\n * The option is intended for exporting values to the caller.\n */\n#define AV_OPT_FLAG_EXPORT          64\n/**\n * The option may not be set through the AVOptions API, only read.\n * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set.\n */\n#define AV_OPT_FLAG_READONLY        128\n#define AV_OPT_FLAG_BSF_PARAM       (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering\n#define AV_OPT_FLAG_RUNTIME_PARAM   (1<<15) ///< a generic parameter which can be set by the user at runtime\n#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering\n#define AV_OPT_FLAG_DEPRECATED      (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information\n#define AV_OPT_FLAG_CHILD_CONSTS    (1<<18) ///< set if option constants can also reside in child objects\n//FIXME think about enc-audio, ... style flags\n\n    /**\n     * The logical unit to which the option belongs. Non-constant\n     * options and corresponding named constants share the same\n     * unit. May be NULL.\n     */\n    const char *unit;\n} AVOption;\n\n/**\n * A single allowed range of values, or a single allowed value.\n */\ntypedef struct AVOptionRange {\n    const char *str;\n    /**\n     * Value range.\n     * For string ranges this represents the min/max length.\n     * For dimensions this represents the min/max pixel count or width/height in multi-component case.\n     */\n    double value_min, value_max;\n    /**\n     * Value's component range.\n     * For string this represents the unicode range for chars, 0-127 limits to ASCII.\n     */\n    double component_min, component_max;\n    /**\n     * Range flag.\n     * If set to 1 the struct encodes a range, if set to 0 a single value.\n     */\n    int is_range;\n} AVOptionRange;\n\n/**\n * List of AVOptionRange structs.\n */\ntypedef struct AVOptionRanges {\n    /**\n     * Array of option ranges.\n     *\n     * Most of option types use just one component.\n     * Following describes multi-component option types:\n     *\n     * AV_OPT_TYPE_IMAGE_SIZE:\n     * component index 0: range of pixel count (width * height).\n     * component index 1: range of width.\n     * component index 2: range of height.\n     *\n     * @note To obtain multi-component version of this structure, user must\n     *       provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or\n     *       av_opt_query_ranges_default function.\n     *\n     * Multi-component range can be read as in following example:\n     *\n     * @code\n     * int range_index, component_index;\n     * AVOptionRanges *ranges;\n     * AVOptionRange *range[3]; //may require more than 3 in the future.\n     * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE);\n     * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) {\n     *     for (component_index = 0; component_index < ranges->nb_components; component_index++)\n     *         range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index];\n     *     //do something with range here.\n     * }\n     * av_opt_freep_ranges(&ranges);\n     * @endcode\n     */\n    AVOptionRange **range;\n    /**\n     * Number of ranges per component.\n     */\n    int nb_ranges;\n    /**\n     * Number of componentes.\n     */\n    int nb_components;\n} AVOptionRanges;\n\n/**\n * Show the obj options.\n *\n * @param req_flags requested flags for the options to show. Show only the\n * options for which it is opt->flags & req_flags.\n * @param rej_flags rejected flags for the options to show. Show only the\n * options for which it is !(opt->flags & req_flags).\n * @param av_log_obj log context to use for showing the options\n */\nint av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags);\n\n/**\n * Set the values of all AVOption fields to their default values.\n *\n * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass)\n */\nvoid av_opt_set_defaults(void *s);\n\n/**\n * Set the values of all AVOption fields to their default values. Only these\n * AVOption fields for which (opt->flags & mask) == flags will have their\n * default applied to s.\n *\n * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass)\n * @param mask combination of AV_OPT_FLAG_*\n * @param flags combination of AV_OPT_FLAG_*\n */\nvoid av_opt_set_defaults2(void *s, int mask, int flags);\n\n/**\n * Parse the key/value pairs list in opts. For each key/value pair\n * found, stores the value in the field in ctx that is named like the\n * key. ctx must be an AVClass context, storing is done using\n * AVOptions.\n *\n * @param opts options string to parse, may be NULL\n * @param key_val_sep a 0-terminated list of characters used to\n * separate key from value\n * @param pairs_sep a 0-terminated list of characters used to separate\n * two pairs from each other\n * @return the number of successfully set key/value pairs, or a negative\n * value corresponding to an AVERROR code in case of error:\n * AVERROR(EINVAL) if opts cannot be parsed,\n * the error code issued by av_opt_set() if a key/value pair\n * cannot be set\n */\nint av_set_options_string(void *ctx, const char *opts,\n                          const char *key_val_sep, const char *pairs_sep);\n\n/**\n * Parse the key-value pairs list in opts. For each key=value pair found,\n * set the value of the corresponding option in ctx.\n *\n * @param ctx          the AVClass object to set options on\n * @param opts         the options string, key-value pairs separated by a\n *                     delimiter\n * @param shorthand    a NULL-terminated array of options names for shorthand\n *                     notation: if the first field in opts has no key part,\n *                     the key is taken from the first element of shorthand;\n *                     then again for the second, etc., until either opts is\n *                     finished, shorthand is finished or a named option is\n *                     found; after that, all options must be named\n * @param key_val_sep  a 0-terminated list of characters used to separate\n *                     key from value, for example '='\n * @param pairs_sep    a 0-terminated list of characters used to separate\n *                     two pairs from each other, for example ':' or ','\n * @return  the number of successfully set key=value pairs, or a negative\n *          value corresponding to an AVERROR code in case of error:\n *          AVERROR(EINVAL) if opts cannot be parsed,\n *          the error code issued by av_set_string3() if a key/value pair\n *          cannot be set\n *\n * Options names must use only the following characters: a-z A-Z 0-9 - . / _\n * Separators must use characters distinct from option names and from each\n * other.\n */\nint av_opt_set_from_string(void *ctx, const char *opts,\n                           const char *const *shorthand,\n                           const char *key_val_sep, const char *pairs_sep);\n/**\n * Free all allocated objects in obj.\n */\nvoid av_opt_free(void *obj);\n\n/**\n * Check whether a particular flag is set in a flags field.\n *\n * @param field_name the name of the flag field option\n * @param flag_name the name of the flag to check\n * @return non-zero if the flag is set, zero if the flag isn't set,\n *         isn't of the right type, or the flags field doesn't exist.\n */\nint av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name);\n\n/**\n * Set all the options from a given dictionary on an object.\n *\n * @param obj a struct whose first element is a pointer to AVClass\n * @param options options to process. This dictionary will be freed and replaced\n *                by a new one containing all options not found in obj.\n *                Of course this new dictionary needs to be freed by caller\n *                with av_dict_free().\n *\n * @return 0 on success, a negative AVERROR if some option was found in obj,\n *         but could not be set.\n *\n * @see av_dict_copy()\n */\nint av_opt_set_dict(void *obj, struct AVDictionary **options);\n\n\n/**\n * Set all the options from a given dictionary on an object.\n *\n * @param obj a struct whose first element is a pointer to AVClass\n * @param options options to process. This dictionary will be freed and replaced\n *                by a new one containing all options not found in obj.\n *                Of course this new dictionary needs to be freed by caller\n *                with av_dict_free().\n * @param search_flags A combination of AV_OPT_SEARCH_*.\n *\n * @return 0 on success, a negative AVERROR if some option was found in obj,\n *         but could not be set.\n *\n * @see av_dict_copy()\n */\nint av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags);\n\n/**\n * Extract a key-value pair from the beginning of a string.\n *\n * @param ropts        pointer to the options string, will be updated to\n *                     point to the rest of the string (one of the pairs_sep\n *                     or the final NUL)\n * @param key_val_sep  a 0-terminated list of characters used to separate\n *                     key from value, for example '='\n * @param pairs_sep    a 0-terminated list of characters used to separate\n *                     two pairs from each other, for example ':' or ','\n * @param flags        flags; see the AV_OPT_FLAG_* values below\n * @param rkey         parsed key; must be freed using av_free()\n * @param rval         parsed value; must be freed using av_free()\n *\n * @return  >=0 for success, or a negative value corresponding to an\n *          AVERROR code in case of error; in particular:\n *          AVERROR(EINVAL) if no key is present\n *\n */\nint av_opt_get_key_value(const char **ropts,\n                         const char *key_val_sep, const char *pairs_sep,\n                         unsigned flags,\n                         char **rkey, char **rval);\n\nenum {\n\n    /**\n     * Accept to parse a value without a key; the key will then be returned\n     * as NULL.\n     */\n    AV_OPT_FLAG_IMPLICIT_KEY = 1,\n};\n\n/**\n * @defgroup opt_eval_funcs Evaluating option strings\n * @{\n * This group of functions can be used to evaluate option strings\n * and get numbers out of them. They do the same thing as av_opt_set(),\n * except the result is written into the caller-supplied pointer.\n *\n * @param obj a struct whose first element is a pointer to AVClass.\n * @param o an option for which the string is to be evaluated.\n * @param val string to be evaluated.\n * @param *_out value of the string will be written here.\n *\n * @return 0 on success, a negative number on failure.\n */\nint av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int        *flags_out);\nint av_opt_eval_int   (void *obj, const AVOption *o, const char *val, int        *int_out);\nint av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t    *int64_out);\nint av_opt_eval_float (void *obj, const AVOption *o, const char *val, float      *float_out);\nint av_opt_eval_double(void *obj, const AVOption *o, const char *val, double     *double_out);\nint av_opt_eval_q     (void *obj, const AVOption *o, const char *val, AVRational *q_out);\n/**\n * @}\n */\n\n#define AV_OPT_SEARCH_CHILDREN   (1 << 0) /**< Search in possible children of the\n                                               given object first. */\n/**\n *  The obj passed to av_opt_find() is fake -- only a double pointer to AVClass\n *  instead of a required pointer to a struct containing AVClass. This is\n *  useful for searching for options without needing to allocate the corresponding\n *  object.\n */\n#define AV_OPT_SEARCH_FAKE_OBJ   (1 << 1)\n\n/**\n *  In av_opt_get, return NULL if the option has a pointer type and is set to NULL,\n *  rather than returning an empty string.\n */\n#define AV_OPT_ALLOW_NULL (1 << 2)\n\n/**\n *  Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than\n *  one component for certain option types.\n *  @see AVOptionRanges for details.\n */\n#define AV_OPT_MULTI_COMPONENT_RANGE (1 << 12)\n\n/**\n * Look for an option in an object. Consider only options which\n * have all the specified flags set.\n *\n * @param[in] obj A pointer to a struct whose first element is a\n *                pointer to an AVClass.\n *                Alternatively a double pointer to an AVClass, if\n *                AV_OPT_SEARCH_FAKE_OBJ search flag is set.\n * @param[in] name The name of the option to look for.\n * @param[in] unit When searching for named constants, name of the unit\n *                 it belongs to.\n * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG).\n * @param search_flags A combination of AV_OPT_SEARCH_*.\n *\n * @return A pointer to the option found, or NULL if no option\n *         was found.\n *\n * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable\n * directly with av_opt_set(). Use special calls which take an options\n * AVDictionary (e.g. avformat_open_input()) to set options found with this\n * flag.\n */\nconst AVOption *av_opt_find(void *obj, const char *name, const char *unit,\n                            int opt_flags, int search_flags);\n\n/**\n * Look for an option in an object. Consider only options which\n * have all the specified flags set.\n *\n * @param[in] obj A pointer to a struct whose first element is a\n *                pointer to an AVClass.\n *                Alternatively a double pointer to an AVClass, if\n *                AV_OPT_SEARCH_FAKE_OBJ search flag is set.\n * @param[in] name The name of the option to look for.\n * @param[in] unit When searching for named constants, name of the unit\n *                 it belongs to.\n * @param opt_flags Find only options with all the specified flags set (AV_OPT_FLAG).\n * @param search_flags A combination of AV_OPT_SEARCH_*.\n * @param[out] target_obj if non-NULL, an object to which the option belongs will be\n * written here. It may be different from obj if AV_OPT_SEARCH_CHILDREN is present\n * in search_flags. This parameter is ignored if search_flags contain\n * AV_OPT_SEARCH_FAKE_OBJ.\n *\n * @return A pointer to the option found, or NULL if no option\n *         was found.\n */\nconst AVOption *av_opt_find2(void *obj, const char *name, const char *unit,\n                             int opt_flags, int search_flags, void **target_obj);\n\n/**\n * Iterate over all AVOptions belonging to obj.\n *\n * @param obj an AVOptions-enabled struct or a double pointer to an\n *            AVClass describing it.\n * @param prev result of the previous call to av_opt_next() on this object\n *             or NULL\n * @return next AVOption or NULL\n */\nconst AVOption *av_opt_next(const void *obj, const AVOption *prev);\n\n/**\n * Iterate over AVOptions-enabled children of obj.\n *\n * @param prev result of a previous call to this function or NULL\n * @return next AVOptions-enabled child or NULL\n */\nvoid *av_opt_child_next(void *obj, void *prev);\n\n/**\n * Iterate over potential AVOptions-enabled children of parent.\n *\n * @param iter a pointer where iteration state is stored.\n * @return AVClass corresponding to next potential child or NULL\n */\nconst AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter);\n\n/**\n * @defgroup opt_set_funcs Option setting functions\n * @{\n * Those functions set the field of obj with the given name to value.\n *\n * @param[in] obj A struct whose first element is a pointer to an AVClass.\n * @param[in] name the name of the field to set\n * @param[in] val The value to set. In case of av_opt_set() if the field is not\n * of a string type, then the given string is parsed.\n * SI postfixes and some named scalars are supported.\n * If the field is of a numeric type, it has to be a numeric or named\n * scalar. Behavior with more than one scalar and +- infix operators\n * is undefined.\n * If the field is of a flags type, it has to be a sequence of numeric\n * scalars or named flags separated by '+' or '-'. Prefixing a flag\n * with '+' causes it to be set without affecting the other flags;\n * similarly, '-' unsets a flag.\n * If the field is of a dictionary type, it has to be a ':' separated list of\n * key=value parameters. Values containing ':' special characters must be\n * escaped.\n * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN\n * is passed here, then the option may be set on a child of obj.\n *\n * @return 0 if the value has been set, or an AVERROR code in case of\n * error:\n * AVERROR_OPTION_NOT_FOUND if no matching option exists\n * AVERROR(ERANGE) if the value is out of range\n * AVERROR(EINVAL) if the value is not valid\n */\nint av_opt_set         (void *obj, const char *name, const char *val, int search_flags);\nint av_opt_set_int     (void *obj, const char *name, int64_t     val, int search_flags);\nint av_opt_set_double  (void *obj, const char *name, double      val, int search_flags);\nint av_opt_set_q       (void *obj, const char *name, AVRational  val, int search_flags);\nint av_opt_set_bin     (void *obj, const char *name, const uint8_t *val, int size, int search_flags);\nint av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags);\nint av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags);\nint av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags);\nint av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags);\n#if FF_API_OLD_CHANNEL_LAYOUT\nattribute_deprecated\nint av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags);\n#endif\nint av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *layout, int search_flags);\n/**\n * @note Any old dictionary present is discarded and replaced with a copy of the new one. The\n * caller still owns val is and responsible for freeing it.\n */\nint av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags);\n\n/**\n * Set a binary option to an integer list.\n *\n * @param obj    AVClass object to set options on\n * @param name   name of the binary option\n * @param val    pointer to an integer list (must have the correct type with\n *               regard to the contents of the list)\n * @param term   list terminator (usually 0 or -1)\n * @param flags  search flags\n */\n#define av_opt_set_int_list(obj, name, val, term, flags) \\\n    (av_int_list_length(val, term) > INT_MAX / sizeof(*(val)) ? \\\n     AVERROR(EINVAL) : \\\n     av_opt_set_bin(obj, name, (const uint8_t *)(val), \\\n                    av_int_list_length(val, term) * sizeof(*(val)), flags))\n\n/**\n * @}\n */\n\n/**\n * @defgroup opt_get_funcs Option getting functions\n * @{\n * Those functions get a value of the option with the given name from an object.\n *\n * @param[in] obj a struct whose first element is a pointer to an AVClass.\n * @param[in] name name of the option to get.\n * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN\n * is passed here, then the option may be found in a child of obj.\n * @param[out] out_val value of the option will be written here\n * @return >=0 on success, a negative error code otherwise\n */\n/**\n * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller\n *\n * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the\n * option is of type AV_OPT_TYPE_STRING, AV_OPT_TYPE_BINARY or AV_OPT_TYPE_DICT\n * and is set to NULL, *out_val will be set to NULL instead of an allocated\n * empty string.\n */\nint av_opt_get         (void *obj, const char *name, int search_flags, uint8_t   **out_val);\nint av_opt_get_int     (void *obj, const char *name, int search_flags, int64_t    *out_val);\nint av_opt_get_double  (void *obj, const char *name, int search_flags, double     *out_val);\nint av_opt_get_q       (void *obj, const char *name, int search_flags, AVRational *out_val);\nint av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out);\nint av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt);\nint av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt);\nint av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val);\n#if FF_API_OLD_CHANNEL_LAYOUT\nattribute_deprecated\nint av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout);\n#endif\nint av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *layout);\n/**\n * @param[out] out_val The returned dictionary is a copy of the actual value and must\n * be freed with av_dict_free() by the caller\n */\nint av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val);\n/**\n * @}\n */\n/**\n * Gets a pointer to the requested field in a struct.\n * This function allows accessing a struct even when its fields are moved or\n * renamed since the application making the access has been compiled,\n *\n * @returns a pointer to the field, it can be cast to the correct type and read\n *          or written to.\n */\nvoid *av_opt_ptr(const AVClass *avclass, void *obj, const char *name);\n\n/**\n * Free an AVOptionRanges struct and set it to NULL.\n */\nvoid av_opt_freep_ranges(AVOptionRanges **ranges);\n\n/**\n * Get a list of allowed ranges for the given option.\n *\n * The returned list may depend on other fields in obj like for example profile.\n *\n * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored\n *              AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance\n *              AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges\n *\n * The result must be freed with av_opt_freep_ranges.\n *\n * @return number of compontents returned on success, a negative errro code otherwise\n */\nint av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags);\n\n/**\n * Copy options from src object into dest object.\n *\n * The underlying AVClass of both src and dest must coincide. The guarantee\n * below does not apply if this is not fulfilled.\n *\n * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object.\n * Original memory allocated for such options is freed unless both src and dest options points to the same memory.\n *\n * Even on error it is guaranteed that allocated options from src and dest\n * no longer alias each other afterwards; in particular calling av_opt_free()\n * on both src and dest is safe afterwards if dest has been memdup'ed from src.\n *\n * @param dest Object to copy from\n * @param src  Object to copy into\n * @return 0 on success, negative on error\n */\nint av_opt_copy(void *dest, const void *src);\n\n/**\n * Get a default list of allowed ranges for the given option.\n *\n * This list is constructed without using the AVClass.query_ranges() callback\n * and can be used as fallback from within the callback.\n *\n * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored\n *              AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance\n *              AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges\n *\n * The result must be freed with av_opt_free_ranges.\n *\n * @return number of compontents returned on success, a negative errro code otherwise\n */\nint av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags);\n\n/**\n * Check if given option is set to its default value.\n *\n * Options o must belong to the obj. This function must not be called to check child's options state.\n * @see av_opt_is_set_to_default_by_name().\n *\n * @param obj  AVClass object to check option on\n * @param o    option to be checked\n * @return     >0 when option is set to its default,\n *              0 when option is not set its default,\n *             <0 on error\n */\nint av_opt_is_set_to_default(void *obj, const AVOption *o);\n\n/**\n * Check if given option is set to its default value.\n *\n * @param obj          AVClass object to check option on\n * @param name         option name\n * @param search_flags combination of AV_OPT_SEARCH_*\n * @return             >0 when option is set to its default,\n *                     0 when option is not set its default,\n *                     <0 on error\n */\nint av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags);\n\n\n#define AV_OPT_SERIALIZE_SKIP_DEFAULTS              0x00000001  ///< Serialize options that are not set to default values only.\n#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT            0x00000002  ///< Serialize options that exactly match opt_flags only.\n\n/**\n * Serialize object's options.\n *\n * Create a string containing object's serialized options.\n * Such string may be passed back to av_opt_set_from_string() in order to restore option values.\n * A key/value or pairs separator occurring in the serialized value or\n * name string are escaped through the av_escape() function.\n *\n * @param[in]  obj           AVClass object to serialize\n * @param[in]  opt_flags     serialize options with all the specified flags set (AV_OPT_FLAG)\n * @param[in]  flags         combination of AV_OPT_SERIALIZE_* flags\n * @param[out] buffer        Pointer to buffer that will be allocated with string containg serialized options.\n *                           Buffer must be freed by the caller when is no longer needed.\n * @param[in]  key_val_sep   character used to separate key from value\n * @param[in]  pairs_sep     character used to separate two pairs from each other\n * @return                   >= 0 on success, negative on error\n * @warning Separators cannot be neither '\\\\' nor '\\0'. They also cannot be the same.\n */\nint av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,\n                     const char key_val_sep, const char pairs_sep);\n/**\n * @}\n */\n\n#endif /* AVUTIL_OPT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/parseutils.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_PARSEUTILS_H\n#define AVUTIL_PARSEUTILS_H\n\n#include <time.h>\n\n#include \"rational.h\"\n\n/**\n * @file\n * misc parsing utilities\n */\n\n/**\n * Parse str and store the parsed ratio in q.\n *\n * Note that a ratio with infinite (1/0) or negative value is\n * considered valid, so you should check on the returned value if you\n * want to exclude those values.\n *\n * The undefined value can be expressed using the \"0:0\" string.\n *\n * @param[in,out] q pointer to the AVRational which will contain the ratio\n * @param[in] str the string to parse: it has to be a string in the format\n * num:den, a float number or an expression\n * @param[in] max the maximum allowed numerator and denominator\n * @param[in] log_offset log level offset which is applied to the log\n * level of log_ctx\n * @param[in] log_ctx parent logging context\n * @return >= 0 on success, a negative error code otherwise\n */\nint av_parse_ratio(AVRational *q, const char *str, int max,\n                   int log_offset, void *log_ctx);\n\n#define av_parse_ratio_quiet(rate, str, max) \\\n    av_parse_ratio(rate, str, max, AV_LOG_MAX_OFFSET, NULL)\n\n/**\n * Parse str and put in width_ptr and height_ptr the detected values.\n *\n * @param[in,out] width_ptr pointer to the variable which will contain the detected\n * width value\n * @param[in,out] height_ptr pointer to the variable which will contain the detected\n * height value\n * @param[in] str the string to parse: it has to be a string in the format\n * width x height or a valid video size abbreviation.\n * @return >= 0 on success, a negative error code otherwise\n */\nint av_parse_video_size(int *width_ptr, int *height_ptr, const char *str);\n\n/**\n * Parse str and store the detected values in *rate.\n *\n * @param[in,out] rate pointer to the AVRational which will contain the detected\n * frame rate\n * @param[in] str the string to parse: it has to be a string in the format\n * rate_num / rate_den, a float number or a valid video rate abbreviation\n * @return >= 0 on success, a negative error code otherwise\n */\nint av_parse_video_rate(AVRational *rate, const char *str);\n\n/**\n * Put the RGBA values that correspond to color_string in rgba_color.\n *\n * @param color_string a string specifying a color. It can be the name of\n * a color (case insensitive match) or a [0x|#]RRGGBB[AA] sequence,\n * possibly followed by \"@\" and a string representing the alpha\n * component.\n * The alpha component may be a string composed by \"0x\" followed by an\n * hexadecimal number or a decimal number between 0.0 and 1.0, which\n * represents the opacity value (0x00/0.0 means completely transparent,\n * 0xff/1.0 completely opaque).\n * If the alpha component is not specified then 0xff is assumed.\n * The string \"random\" will result in a random color.\n * @param slen length of the initial part of color_string containing the\n * color. It can be set to -1 if color_string is a null terminated string\n * containing nothing else than the color.\n * @return >= 0 in case of success, a negative value in case of\n * failure (for example if color_string cannot be parsed).\n */\nint av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,\n                   void *log_ctx);\n\n/**\n * Get the name of a color from the internal table of hard-coded named\n * colors.\n *\n * This function is meant to enumerate the color names recognized by\n * av_parse_color().\n *\n * @param color_idx index of the requested color, starting from 0\n * @param rgbp      if not NULL, will point to a 3-elements array with the color value in RGB\n * @return the color name string or NULL if color_idx is not in the array\n */\nconst char *av_get_known_color_name(int color_idx, const uint8_t **rgb);\n\n/**\n * Parse timestr and return in *time a corresponding number of\n * microseconds.\n *\n * @param timeval puts here the number of microseconds corresponding\n * to the string in timestr. If the string represents a duration, it\n * is the number of microseconds contained in the time interval.  If\n * the string is a date, is the number of microseconds since 1st of\n * January, 1970 up to the time of the parsed date.  If timestr cannot\n * be successfully parsed, set *time to INT64_MIN.\n\n * @param timestr a string representing a date or a duration.\n * - If a date the syntax is:\n * @code\n * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH:MM:SS[.m...]]]}|{HHMMSS[.m...]]]}}[Z]\n * now\n * @endcode\n * If the value is \"now\" it takes the current time.\n * Time is local time unless Z is appended, in which case it is\n * interpreted as UTC.\n * If the year-month-day part is not specified it takes the current\n * year-month-day.\n * - If a duration the syntax is:\n * @code\n * [-][HH:]MM:SS[.m...]\n * [-]S+[.m...]\n * @endcode\n * @param duration flag which tells how to interpret timestr, if not\n * zero timestr is interpreted as a duration, otherwise as a date\n * @return >= 0 in case of success, a negative value corresponding to an\n * AVERROR code otherwise\n */\nint av_parse_time(int64_t *timeval, const char *timestr, int duration);\n\n/**\n * Attempt to find a specific tag in a URL.\n *\n * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done.\n * Return 1 if found.\n */\nint av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info);\n\n/**\n * Simplified version of strptime\n *\n * Parse the input string p according to the format string fmt and\n * store its results in the structure dt.\n * This implementation supports only a subset of the formats supported\n * by the standard strptime().\n *\n * The supported input field descriptors are listed below.\n * - %H: the hour as a decimal number, using a 24-hour clock, in the\n *   range '00' through '23'\n * - %J: hours as a decimal number, in the range '0' through INT_MAX\n * - %M: the minute as a decimal number, using a 24-hour clock, in the\n *   range '00' through '59'\n * - %S: the second as a decimal number, using a 24-hour clock, in the\n *   range '00' through '59'\n * - %Y: the year as a decimal number, using the Gregorian calendar\n * - %m: the month as a decimal number, in the range '1' through '12'\n * - %d: the day of the month as a decimal number, in the range '1'\n *   through '31'\n * - %T: alias for '%H:%M:%S'\n * - %%: a literal '%'\n *\n * @return a pointer to the first character not processed in this function\n *         call. In case the input string contains more characters than\n *         required by the format string the return value points right after\n *         the last consumed input character. In case the whole input string\n *         is consumed the return value points to the null byte at the end of\n *         the string. On failure NULL is returned.\n */\nchar *av_small_strptime(const char *p, const char *fmt, struct tm *dt);\n\n/**\n * Convert the decomposed UTC time in tm to a time_t value.\n */\ntime_t av_timegm(struct tm *tm);\n\n#endif /* AVUTIL_PARSEUTILS_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/pixdesc.h",
    "content": "/*\n * pixel format descriptor\n * Copyright (c) 2009 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_PIXDESC_H\n#define AVUTIL_PIXDESC_H\n\n#include <inttypes.h>\n\n#include \"attributes.h\"\n#include \"pixfmt.h\"\n\ntypedef struct AVComponentDescriptor {\n    /**\n     * Which of the 4 planes contains the component.\n     */\n    int plane;\n\n    /**\n     * Number of elements between 2 horizontally consecutive pixels.\n     * Elements are bits for bitstream formats, bytes otherwise.\n     */\n    int step;\n\n    /**\n     * Number of elements before the component of the first pixel.\n     * Elements are bits for bitstream formats, bytes otherwise.\n     */\n    int offset;\n\n    /**\n     * Number of least significant bits that must be shifted away\n     * to get the value.\n     */\n    int shift;\n\n    /**\n     * Number of bits in the component.\n     */\n    int depth;\n} AVComponentDescriptor;\n\n/**\n * Descriptor that unambiguously describes how the bits of a pixel are\n * stored in the up to 4 data planes of an image. It also stores the\n * subsampling factors and number of components.\n *\n * @note This is separate of the colorspace (RGB, YCbCr, YPbPr, JPEG-style YUV\n *       and all the YUV variants) AVPixFmtDescriptor just stores how values\n *       are stored not what these values represent.\n */\ntypedef struct AVPixFmtDescriptor {\n    const char *name;\n    uint8_t nb_components;  ///< The number of components each pixel has, (1-4)\n\n    /**\n     * Amount to shift the luma width right to find the chroma width.\n     * For YV12 this is 1 for example.\n     * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w)\n     * The note above is needed to ensure rounding up.\n     * This value only refers to the chroma components.\n     */\n    uint8_t log2_chroma_w;\n\n    /**\n     * Amount to shift the luma height right to find the chroma height.\n     * For YV12 this is 1 for example.\n     * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h)\n     * The note above is needed to ensure rounding up.\n     * This value only refers to the chroma components.\n     */\n    uint8_t log2_chroma_h;\n\n    /**\n     * Combination of AV_PIX_FMT_FLAG_... flags.\n     */\n    uint64_t flags;\n\n    /**\n     * Parameters that describe how pixels are packed.\n     * If the format has 1 or 2 components, then luma is 0.\n     * If the format has 3 or 4 components:\n     *   if the RGB flag is set then 0 is red, 1 is green and 2 is blue;\n     *   otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V.\n     *\n     * If present, the Alpha channel is always the last component.\n     */\n    AVComponentDescriptor comp[4];\n\n    /**\n     * Alternative comma-separated names.\n     */\n    const char *alias;\n} AVPixFmtDescriptor;\n\n/**\n * Pixel format is big-endian.\n */\n#define AV_PIX_FMT_FLAG_BE           (1 << 0)\n/**\n * Pixel format has a palette in data[1], values are indexes in this palette.\n */\n#define AV_PIX_FMT_FLAG_PAL          (1 << 1)\n/**\n * All values of a component are bit-wise packed end to end.\n */\n#define AV_PIX_FMT_FLAG_BITSTREAM    (1 << 2)\n/**\n * Pixel format is an HW accelerated format.\n */\n#define AV_PIX_FMT_FLAG_HWACCEL      (1 << 3)\n/**\n * At least one pixel component is not in the first data plane.\n */\n#define AV_PIX_FMT_FLAG_PLANAR       (1 << 4)\n/**\n * The pixel format contains RGB-like data (as opposed to YUV/grayscale).\n */\n#define AV_PIX_FMT_FLAG_RGB          (1 << 5)\n\n/**\n * The pixel format has an alpha channel. This is set on all formats that\n * support alpha in some way, including AV_PIX_FMT_PAL8. The alpha is always\n * straight, never pre-multiplied.\n *\n * If a codec or a filter does not support alpha, it should set all alpha to\n * opaque, or use the equivalent pixel formats without alpha component, e.g.\n * AV_PIX_FMT_RGB0 (or AV_PIX_FMT_RGB24 etc.) instead of AV_PIX_FMT_RGBA.\n */\n#define AV_PIX_FMT_FLAG_ALPHA        (1 << 7)\n\n/**\n * The pixel format is following a Bayer pattern\n */\n#define AV_PIX_FMT_FLAG_BAYER        (1 << 8)\n\n/**\n * The pixel format contains IEEE-754 floating point values. Precision (double,\n * single, or half) should be determined by the pixel size (64, 32, or 16 bits).\n */\n#define AV_PIX_FMT_FLAG_FLOAT        (1 << 9)\n\n/**\n * Return the number of bits per pixel used by the pixel format\n * described by pixdesc. Note that this is not the same as the number\n * of bits per sample.\n *\n * The returned number of bits refers to the number of bits actually\n * used for storing the pixel information, that is padding bits are\n * not counted.\n */\nint av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc);\n\n/**\n * Return the number of bits per pixel for the pixel format\n * described by pixdesc, including any padding or unused bits.\n */\nint av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc);\n\n/**\n * @return a pixel format descriptor for provided pixel format or NULL if\n * this pixel format is unknown.\n */\nconst AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt);\n\n/**\n * Iterate over all pixel format descriptors known to libavutil.\n *\n * @param prev previous descriptor. NULL to get the first descriptor.\n *\n * @return next descriptor or NULL after the last descriptor\n */\nconst AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev);\n\n/**\n * @return an AVPixelFormat id described by desc, or AV_PIX_FMT_NONE if desc\n * is not a valid pointer to a pixel format descriptor.\n */\nenum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc);\n\n/**\n * Utility function to access log2_chroma_w log2_chroma_h from\n * the pixel format AVPixFmtDescriptor.\n *\n * @param[in]  pix_fmt the pixel format\n * @param[out] h_shift store log2_chroma_w (horizontal/width shift)\n * @param[out] v_shift store log2_chroma_h (vertical/height shift)\n *\n * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format\n */\nint av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt,\n                                     int *h_shift, int *v_shift);\n\n/**\n * @return number of planes in pix_fmt, a negative AVERROR if pix_fmt is not a\n * valid pixel format.\n */\nint av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt);\n\n/**\n * @return the name for provided color range or NULL if unknown.\n */\nconst char *av_color_range_name(enum AVColorRange range);\n\n/**\n * @return the AVColorRange value for name or an AVError if not found.\n */\nint av_color_range_from_name(const char *name);\n\n/**\n * @return the name for provided color primaries or NULL if unknown.\n */\nconst char *av_color_primaries_name(enum AVColorPrimaries primaries);\n\n/**\n * @return the AVColorPrimaries value for name or an AVError if not found.\n */\nint av_color_primaries_from_name(const char *name);\n\n/**\n * @return the name for provided color transfer or NULL if unknown.\n */\nconst char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer);\n\n/**\n * @return the AVColorTransferCharacteristic value for name or an AVError if not found.\n */\nint av_color_transfer_from_name(const char *name);\n\n/**\n * @return the name for provided color space or NULL if unknown.\n */\nconst char *av_color_space_name(enum AVColorSpace space);\n\n/**\n * @return the AVColorSpace value for name or an AVError if not found.\n */\nint av_color_space_from_name(const char *name);\n\n/**\n * @return the name for provided chroma location or NULL if unknown.\n */\nconst char *av_chroma_location_name(enum AVChromaLocation location);\n\n/**\n * @return the AVChromaLocation value for name or an AVError if not found.\n */\nint av_chroma_location_from_name(const char *name);\n\n/**\n * Return the pixel format corresponding to name.\n *\n * If there is no pixel format with name name, then looks for a\n * pixel format with the name corresponding to the native endian\n * format of name.\n * For example in a little-endian system, first looks for \"gray16\",\n * then for \"gray16le\".\n *\n * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE.\n */\nenum AVPixelFormat av_get_pix_fmt(const char *name);\n\n/**\n * Return the short name for a pixel format, NULL in case pix_fmt is\n * unknown.\n *\n * @see av_get_pix_fmt(), av_get_pix_fmt_string()\n */\nconst char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt);\n\n/**\n * Print in buf the string corresponding to the pixel format with\n * number pix_fmt, or a header if pix_fmt is negative.\n *\n * @param buf the buffer where to write the string\n * @param buf_size the size of buf\n * @param pix_fmt the number of the pixel format to print the\n * corresponding info string, or a negative value to print the\n * corresponding header.\n */\nchar *av_get_pix_fmt_string(char *buf, int buf_size,\n                            enum AVPixelFormat pix_fmt);\n\n/**\n * Read a line from an image, and write the values of the\n * pixel format component c to dst.\n *\n * @param data the array containing the pointers to the planes of the image\n * @param linesize the array containing the linesizes of the image\n * @param desc the pixel format descriptor for the image\n * @param x the horizontal coordinate of the first pixel to read\n * @param y the vertical coordinate of the first pixel to read\n * @param w the width of the line to read, that is the number of\n * values to write to dst\n * @param read_pal_component if not zero and the format is a paletted\n * format writes the values corresponding to the palette\n * component c in data[1] to dst, rather than the palette indexes in\n * data[0]. The behavior is undefined if the format is not paletted.\n * @param dst_element_size size of elements in dst array (2 or 4 byte)\n */\nvoid av_read_image_line2(void *dst, const uint8_t *data[4],\n                        const int linesize[4], const AVPixFmtDescriptor *desc,\n                        int x, int y, int c, int w, int read_pal_component,\n                        int dst_element_size);\n\nvoid av_read_image_line(uint16_t *dst, const uint8_t *data[4],\n                        const int linesize[4], const AVPixFmtDescriptor *desc,\n                        int x, int y, int c, int w, int read_pal_component);\n\n/**\n * Write the values from src to the pixel format component c of an\n * image line.\n *\n * @param src array containing the values to write\n * @param data the array containing the pointers to the planes of the\n * image to write into. It is supposed to be zeroed.\n * @param linesize the array containing the linesizes of the image\n * @param desc the pixel format descriptor for the image\n * @param x the horizontal coordinate of the first pixel to write\n * @param y the vertical coordinate of the first pixel to write\n * @param w the width of the line to write, that is the number of\n * values to write to the image line\n * @param src_element_size size of elements in src array (2 or 4 byte)\n */\nvoid av_write_image_line2(const void *src, uint8_t *data[4],\n                         const int linesize[4], const AVPixFmtDescriptor *desc,\n                         int x, int y, int c, int w, int src_element_size);\n\nvoid av_write_image_line(const uint16_t *src, uint8_t *data[4],\n                         const int linesize[4], const AVPixFmtDescriptor *desc,\n                         int x, int y, int c, int w);\n\n/**\n * Utility function to swap the endianness of a pixel format.\n *\n * @param[in]  pix_fmt the pixel format\n *\n * @return pixel format with swapped endianness if it exists,\n * otherwise AV_PIX_FMT_NONE\n */\nenum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt);\n\n#define FF_LOSS_RESOLUTION  0x0001 /**< loss due to resolution change */\n#define FF_LOSS_DEPTH       0x0002 /**< loss due to color depth change */\n#define FF_LOSS_COLORSPACE  0x0004 /**< loss due to color space conversion */\n#define FF_LOSS_ALPHA       0x0008 /**< loss of alpha bits */\n#define FF_LOSS_COLORQUANT  0x0010 /**< loss due to color quantization */\n#define FF_LOSS_CHROMA      0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */\n\n/**\n * Compute what kind of losses will occur when converting from one specific\n * pixel format to another.\n * When converting from one pixel format to another, information loss may occur.\n * For example, when converting from RGB24 to GRAY, the color information will\n * be lost. Similarly, other losses occur when converting from some formats to\n * other formats. These losses can involve loss of chroma, but also loss of\n * resolution, loss of color depth, loss due to the color space conversion, loss\n * of the alpha bits or loss due to color quantization.\n * av_get_fix_fmt_loss() informs you about the various types of losses\n * which will occur when converting from one pixel format to another.\n *\n * @param[in] dst_pix_fmt destination pixel format\n * @param[in] src_pix_fmt source pixel format\n * @param[in] has_alpha Whether the source pixel format alpha channel is used.\n * @return Combination of flags informing you what kind of losses will occur\n * (maximum loss for an invalid dst_pix_fmt).\n */\nint av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,\n                        enum AVPixelFormat src_pix_fmt,\n                        int has_alpha);\n\n/**\n * Compute what kind of losses will occur when converting from one specific\n * pixel format to another.\n * When converting from one pixel format to another, information loss may occur.\n * For example, when converting from RGB24 to GRAY, the color information will\n * be lost. Similarly, other losses occur when converting from some formats to\n * other formats. These losses can involve loss of chroma, but also loss of\n * resolution, loss of color depth, loss due to the color space conversion, loss\n * of the alpha bits or loss due to color quantization.\n * av_get_fix_fmt_loss() informs you about the various types of losses\n * which will occur when converting from one pixel format to another.\n *\n * @param[in] dst_pix_fmt destination pixel format\n * @param[in] src_pix_fmt source pixel format\n * @param[in] has_alpha Whether the source pixel format alpha channel is used.\n * @return Combination of flags informing you what kind of losses will occur\n * (maximum loss for an invalid dst_pix_fmt).\n */\nenum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,\n                                             enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr);\n\n#endif /* AVUTIL_PIXDESC_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/pixelutils.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_PIXELUTILS_H\n#define AVUTIL_PIXELUTILS_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * Sum of abs(src1[x] - src2[x])\n */\ntypedef int (*av_pixelutils_sad_fn)(const uint8_t *src1, ptrdiff_t stride1,\n                                    const uint8_t *src2, ptrdiff_t stride2);\n\n/**\n * Get a potentially optimized pointer to a Sum-of-absolute-differences\n * function (see the av_pixelutils_sad_fn prototype).\n *\n * @param w_bits  1<<w_bits is the requested width of the block size\n * @param h_bits  1<<h_bits is the requested height of the block size\n * @param aligned If set to 2, the returned sad function will assume src1 and\n *                src2 addresses are aligned on the block size.\n *                If set to 1, the returned sad function will assume src1 is\n *                aligned on the block size.\n *                If set to 0, the returned sad function assume no particular\n *                alignment.\n * @param log_ctx context used for logging, can be NULL\n *\n * @return a pointer to the SAD function or NULL in case of error (because of\n *         invalid parameters)\n */\nav_pixelutils_sad_fn av_pixelutils_get_sad_fn(int w_bits, int h_bits,\n                                              int aligned, void *log_ctx);\n\n#endif /* AVUTIL_PIXELUTILS_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/pixfmt.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_PIXFMT_H\n#define AVUTIL_PIXFMT_H\n\n/**\n * @file\n * pixel format definitions\n */\n\n#include \"libavutil/avconfig.h\"\n#include \"version.h\"\n\n#define AVPALETTE_SIZE 1024\n#define AVPALETTE_COUNT 256\n\n/**\n * Pixel format.\n *\n * @note\n * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA\n * color is put together as:\n *  (A << 24) | (R << 16) | (G << 8) | B\n * This is stored as BGRA on little-endian CPU architectures and ARGB on\n * big-endian CPUs.\n *\n * @note\n * If the resolution is not a multiple of the chroma subsampling factor\n * then the chroma plane resolution must be rounded up.\n *\n * @par\n * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized\n * image data is stored in AVFrame.data[0]. The palette is transported in\n * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is\n * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is\n * also endian-specific). Note also that the individual RGB32 palette\n * components stored in AVFrame.data[1] should be in the range 0..255.\n * This is important as many custom PAL8 video codecs that were designed\n * to run on the IBM VGA graphics adapter use 6-bit palette components.\n *\n * @par\n * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like\n * for pal8. This palette is filled in automatically by the function\n * allocating the picture.\n */\nenum AVPixelFormat {\n    AV_PIX_FMT_NONE = -1,\n    AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)\n    AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr\n    AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...\n    AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...\n    AV_PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)\n    AV_PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)\n    AV_PIX_FMT_YUV410P,   ///< planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)\n    AV_PIX_FMT_YUV411P,   ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)\n    AV_PIX_FMT_GRAY8,     ///<        Y        ,  8bpp\n    AV_PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb\n    AV_PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb\n    AV_PIX_FMT_PAL8,      ///< 8 bits with AV_PIX_FMT_RGB32 palette\n    AV_PIX_FMT_YUVJ420P,  ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range\n    AV_PIX_FMT_YUVJ422P,  ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range\n    AV_PIX_FMT_YUVJ444P,  ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range\n    AV_PIX_FMT_UYVY422,   ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1\n    AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3\n    AV_PIX_FMT_BGR8,      ///< packed RGB 3:3:2,  8bpp, (msb)2B 3G 3R(lsb)\n    AV_PIX_FMT_BGR4,      ///< packed RGB 1:2:1 bitstream,  4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits\n    AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)\n    AV_PIX_FMT_RGB8,      ///< packed RGB 3:3:2,  8bpp, (msb)2R 3G 3B(lsb)\n    AV_PIX_FMT_RGB4,      ///< packed RGB 1:2:1 bitstream,  4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits\n    AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1R 2G 1B(lsb)\n    AV_PIX_FMT_NV12,      ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)\n    AV_PIX_FMT_NV21,      ///< as above, but U and V bytes are swapped\n\n    AV_PIX_FMT_ARGB,      ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...\n    AV_PIX_FMT_RGBA,      ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...\n    AV_PIX_FMT_ABGR,      ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...\n    AV_PIX_FMT_BGRA,      ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...\n\n    AV_PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian\n    AV_PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian\n    AV_PIX_FMT_YUV440P,   ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)\n    AV_PIX_FMT_YUVJ440P,  ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range\n    AV_PIX_FMT_YUVA420P,  ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)\n    AV_PIX_FMT_RGB48BE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian\n    AV_PIX_FMT_RGB48LE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian\n\n    AV_PIX_FMT_RGB565BE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), big-endian\n    AV_PIX_FMT_RGB565LE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), little-endian\n    AV_PIX_FMT_RGB555BE,  ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian   , X=unused/undefined\n    AV_PIX_FMT_RGB555LE,  ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined\n\n    AV_PIX_FMT_BGR565BE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), big-endian\n    AV_PIX_FMT_BGR565LE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), little-endian\n    AV_PIX_FMT_BGR555BE,  ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian   , X=unused/undefined\n    AV_PIX_FMT_BGR555LE,  ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined\n\n    /**\n     *  Hardware acceleration through VA-API, data[3] contains a\n     *  VASurfaceID.\n     */\n    AV_PIX_FMT_VAAPI,\n\n    AV_PIX_FMT_YUV420P16LE,  ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian\n    AV_PIX_FMT_YUV420P16BE,  ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian\n    AV_PIX_FMT_YUV422P16LE,  ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian\n    AV_PIX_FMT_YUV422P16BE,  ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian\n    AV_PIX_FMT_YUV444P16LE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian\n    AV_PIX_FMT_YUV444P16BE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian\n    AV_PIX_FMT_DXVA2_VLD,    ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer\n\n    AV_PIX_FMT_RGB444LE,  ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined\n    AV_PIX_FMT_RGB444BE,  ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian,    X=unused/undefined\n    AV_PIX_FMT_BGR444LE,  ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined\n    AV_PIX_FMT_BGR444BE,  ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian,    X=unused/undefined\n    AV_PIX_FMT_YA8,       ///< 8 bits gray, 8 bits alpha\n\n    AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8\n    AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8\n\n    AV_PIX_FMT_BGR48BE,   ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian\n    AV_PIX_FMT_BGR48LE,   ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian\n\n    /**\n     * The following 12 formats have the disadvantage of needing 1 format for each bit depth.\n     * Notice that each 9/10 bits sample is stored in 16 bits with extra padding.\n     * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better.\n     */\n    AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian\n    AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian\n    AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian\n    AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian\n    AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian\n    AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian\n    AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian\n    AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian\n    AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian\n    AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian\n    AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian\n    AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian\n    AV_PIX_FMT_GBRP,      ///< planar GBR 4:4:4 24bpp\n    AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP\n    AV_PIX_FMT_GBRP9BE,   ///< planar GBR 4:4:4 27bpp, big-endian\n    AV_PIX_FMT_GBRP9LE,   ///< planar GBR 4:4:4 27bpp, little-endian\n    AV_PIX_FMT_GBRP10BE,  ///< planar GBR 4:4:4 30bpp, big-endian\n    AV_PIX_FMT_GBRP10LE,  ///< planar GBR 4:4:4 30bpp, little-endian\n    AV_PIX_FMT_GBRP16BE,  ///< planar GBR 4:4:4 48bpp, big-endian\n    AV_PIX_FMT_GBRP16LE,  ///< planar GBR 4:4:4 48bpp, little-endian\n    AV_PIX_FMT_YUVA422P,  ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)\n    AV_PIX_FMT_YUVA444P,  ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)\n    AV_PIX_FMT_YUVA420P9BE,  ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian\n    AV_PIX_FMT_YUVA420P9LE,  ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian\n    AV_PIX_FMT_YUVA422P9BE,  ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian\n    AV_PIX_FMT_YUVA422P9LE,  ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian\n    AV_PIX_FMT_YUVA444P9BE,  ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian\n    AV_PIX_FMT_YUVA444P9LE,  ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian\n    AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)\n    AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)\n    AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)\n    AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)\n    AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)\n    AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)\n    AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)\n    AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)\n    AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)\n    AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)\n    AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)\n    AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)\n\n    AV_PIX_FMT_VDPAU,     ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface\n\n    AV_PIX_FMT_XYZ12LE,      ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0\n    AV_PIX_FMT_XYZ12BE,      ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0\n    AV_PIX_FMT_NV16,         ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)\n    AV_PIX_FMT_NV20LE,       ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian\n    AV_PIX_FMT_NV20BE,       ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian\n\n    AV_PIX_FMT_RGBA64BE,     ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian\n    AV_PIX_FMT_RGBA64LE,     ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian\n    AV_PIX_FMT_BGRA64BE,     ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian\n    AV_PIX_FMT_BGRA64LE,     ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian\n\n    AV_PIX_FMT_YVYU422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb\n\n    AV_PIX_FMT_YA16BE,       ///< 16 bits gray, 16 bits alpha (big-endian)\n    AV_PIX_FMT_YA16LE,       ///< 16 bits gray, 16 bits alpha (little-endian)\n\n    AV_PIX_FMT_GBRAP,        ///< planar GBRA 4:4:4:4 32bpp\n    AV_PIX_FMT_GBRAP16BE,    ///< planar GBRA 4:4:4:4 64bpp, big-endian\n    AV_PIX_FMT_GBRAP16LE,    ///< planar GBRA 4:4:4:4 64bpp, little-endian\n    /**\n     *  HW acceleration through QSV, data[3] contains a pointer to the\n     *  mfxFrameSurface1 structure.\n     */\n    AV_PIX_FMT_QSV,\n    /**\n     * HW acceleration though MMAL, data[3] contains a pointer to the\n     * MMAL_BUFFER_HEADER_T structure.\n     */\n    AV_PIX_FMT_MMAL,\n\n    AV_PIX_FMT_D3D11VA_VLD,  ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer\n\n    /**\n     * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers\n     * exactly as for system memory frames.\n     */\n    AV_PIX_FMT_CUDA,\n\n    AV_PIX_FMT_0RGB,        ///< packed RGB 8:8:8, 32bpp, XRGBXRGB...   X=unused/undefined\n    AV_PIX_FMT_RGB0,        ///< packed RGB 8:8:8, 32bpp, RGBXRGBX...   X=unused/undefined\n    AV_PIX_FMT_0BGR,        ///< packed BGR 8:8:8, 32bpp, XBGRXBGR...   X=unused/undefined\n    AV_PIX_FMT_BGR0,        ///< packed BGR 8:8:8, 32bpp, BGRXBGRX...   X=unused/undefined\n\n    AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian\n    AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian\n    AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian\n    AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian\n    AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian\n    AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian\n    AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian\n    AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian\n    AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian\n    AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian\n    AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian\n    AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian\n    AV_PIX_FMT_GBRP12BE,    ///< planar GBR 4:4:4 36bpp, big-endian\n    AV_PIX_FMT_GBRP12LE,    ///< planar GBR 4:4:4 36bpp, little-endian\n    AV_PIX_FMT_GBRP14BE,    ///< planar GBR 4:4:4 42bpp, big-endian\n    AV_PIX_FMT_GBRP14LE,    ///< planar GBR 4:4:4 42bpp, little-endian\n    AV_PIX_FMT_YUVJ411P,    ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range\n\n    AV_PIX_FMT_BAYER_BGGR8,    ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples\n    AV_PIX_FMT_BAYER_RGGB8,    ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples\n    AV_PIX_FMT_BAYER_GBRG8,    ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples\n    AV_PIX_FMT_BAYER_GRBG8,    ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples\n    AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian\n    AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian\n    AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian\n    AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian\n    AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian\n    AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian\n    AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian\n    AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian\n\n#if FF_API_XVMC\n    AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing\n#endif\n\n    AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian\n    AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian\n    AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian\n    AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian\n    AV_PIX_FMT_AYUV64LE,    ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian\n    AV_PIX_FMT_AYUV64BE,    ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian\n\n    AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox\n\n    AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian\n    AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian\n\n    AV_PIX_FMT_GBRAP12BE,  ///< planar GBR 4:4:4:4 48bpp, big-endian\n    AV_PIX_FMT_GBRAP12LE,  ///< planar GBR 4:4:4:4 48bpp, little-endian\n\n    AV_PIX_FMT_GBRAP10BE,  ///< planar GBR 4:4:4:4 40bpp, big-endian\n    AV_PIX_FMT_GBRAP10LE,  ///< planar GBR 4:4:4:4 40bpp, little-endian\n\n    AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec\n\n    AV_PIX_FMT_GRAY12BE,   ///<        Y        , 12bpp, big-endian\n    AV_PIX_FMT_GRAY12LE,   ///<        Y        , 12bpp, little-endian\n    AV_PIX_FMT_GRAY10BE,   ///<        Y        , 10bpp, big-endian\n    AV_PIX_FMT_GRAY10LE,   ///<        Y        , 10bpp, little-endian\n\n    AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian\n    AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian\n\n    /**\n     * Hardware surfaces for Direct3D11.\n     *\n     * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11\n     * hwaccel API and filtering support AV_PIX_FMT_D3D11 only.\n     *\n     * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the\n     * texture array index of the frame as intptr_t if the ID3D11Texture2D is\n     * an array texture (or always 0 if it's a normal texture).\n     */\n    AV_PIX_FMT_D3D11,\n\n    AV_PIX_FMT_GRAY9BE,   ///<        Y        , 9bpp, big-endian\n    AV_PIX_FMT_GRAY9LE,   ///<        Y        , 9bpp, little-endian\n\n    AV_PIX_FMT_GBRPF32BE,  ///< IEEE-754 single precision planar GBR 4:4:4,     96bpp, big-endian\n    AV_PIX_FMT_GBRPF32LE,  ///< IEEE-754 single precision planar GBR 4:4:4,     96bpp, little-endian\n    AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian\n    AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian\n\n    /**\n     * DRM-managed buffers exposed through PRIME buffer sharing.\n     *\n     * data[0] points to an AVDRMFrameDescriptor.\n     */\n    AV_PIX_FMT_DRM_PRIME,\n    /**\n     * Hardware surfaces for OpenCL.\n     *\n     * data[i] contain 2D image objects (typed in C as cl_mem, used\n     * in OpenCL as image2d_t) for each plane of the surface.\n     */\n    AV_PIX_FMT_OPENCL,\n\n    AV_PIX_FMT_GRAY14BE,   ///<        Y        , 14bpp, big-endian\n    AV_PIX_FMT_GRAY14LE,   ///<        Y        , 14bpp, little-endian\n\n    AV_PIX_FMT_GRAYF32BE,  ///< IEEE-754 single precision Y, 32bpp, big-endian\n    AV_PIX_FMT_GRAYF32LE,  ///< IEEE-754 single precision Y, 32bpp, little-endian\n\n    AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian\n    AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian\n    AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian\n    AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian\n\n    AV_PIX_FMT_NV24,      ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)\n    AV_PIX_FMT_NV42,      ///< as above, but U and V bytes are swapped\n\n    /**\n     * Vulkan hardware images.\n     *\n     * data[0] points to an AVVkFrame\n     */\n    AV_PIX_FMT_VULKAN,\n\n    AV_PIX_FMT_Y210BE,    ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian\n    AV_PIX_FMT_Y210LE,    ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian\n\n    AV_PIX_FMT_X2RGB10LE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined\n    AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined\n    AV_PIX_FMT_X2BGR10LE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), little-endian, X=unused/undefined\n    AV_PIX_FMT_X2BGR10BE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), big-endian, X=unused/undefined\n\n    AV_PIX_FMT_P210BE,      ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, big-endian\n    AV_PIX_FMT_P210LE,      ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, little-endian\n\n    AV_PIX_FMT_P410BE,      ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, big-endian\n    AV_PIX_FMT_P410LE,      ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, little-endian\n\n    AV_PIX_FMT_P216BE,      ///< interleaved chroma YUV 4:2:2, 32bpp, big-endian\n    AV_PIX_FMT_P216LE,      ///< interleaved chroma YUV 4:2:2, 32bpp, little-endian\n\n    AV_PIX_FMT_P416BE,      ///< interleaved chroma YUV 4:4:4, 48bpp, big-endian\n    AV_PIX_FMT_P416LE,      ///< interleaved chroma YUV 4:4:4, 48bpp, little-endian\n\n    AV_PIX_FMT_NB         ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions\n};\n\n#if AV_HAVE_BIGENDIAN\n#   define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be\n#else\n#   define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le\n#endif\n\n#define AV_PIX_FMT_RGB32   AV_PIX_FMT_NE(ARGB, BGRA)\n#define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR)\n#define AV_PIX_FMT_BGR32   AV_PIX_FMT_NE(ABGR, RGBA)\n#define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB)\n#define AV_PIX_FMT_0RGB32  AV_PIX_FMT_NE(0RGB, BGR0)\n#define AV_PIX_FMT_0BGR32  AV_PIX_FMT_NE(0BGR, RGB0)\n\n#define AV_PIX_FMT_GRAY9  AV_PIX_FMT_NE(GRAY9BE,  GRAY9LE)\n#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE)\n#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE)\n#define AV_PIX_FMT_GRAY14 AV_PIX_FMT_NE(GRAY14BE, GRAY14LE)\n#define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE)\n#define AV_PIX_FMT_YA16   AV_PIX_FMT_NE(YA16BE,   YA16LE)\n#define AV_PIX_FMT_RGB48  AV_PIX_FMT_NE(RGB48BE,  RGB48LE)\n#define AV_PIX_FMT_RGB565 AV_PIX_FMT_NE(RGB565BE, RGB565LE)\n#define AV_PIX_FMT_RGB555 AV_PIX_FMT_NE(RGB555BE, RGB555LE)\n#define AV_PIX_FMT_RGB444 AV_PIX_FMT_NE(RGB444BE, RGB444LE)\n#define AV_PIX_FMT_RGBA64 AV_PIX_FMT_NE(RGBA64BE, RGBA64LE)\n#define AV_PIX_FMT_BGR48  AV_PIX_FMT_NE(BGR48BE,  BGR48LE)\n#define AV_PIX_FMT_BGR565 AV_PIX_FMT_NE(BGR565BE, BGR565LE)\n#define AV_PIX_FMT_BGR555 AV_PIX_FMT_NE(BGR555BE, BGR555LE)\n#define AV_PIX_FMT_BGR444 AV_PIX_FMT_NE(BGR444BE, BGR444LE)\n#define AV_PIX_FMT_BGRA64 AV_PIX_FMT_NE(BGRA64BE, BGRA64LE)\n\n#define AV_PIX_FMT_YUV420P9  AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE)\n#define AV_PIX_FMT_YUV422P9  AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE)\n#define AV_PIX_FMT_YUV444P9  AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE)\n#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE)\n#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE)\n#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE)\n#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE)\n#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE)\n#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE)\n#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE)\n#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE)\n#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE)\n#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE)\n#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE)\n#define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE)\n#define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE)\n#define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE)\n\n#define AV_PIX_FMT_GBRP9     AV_PIX_FMT_NE(GBRP9BE ,    GBRP9LE)\n#define AV_PIX_FMT_GBRP10    AV_PIX_FMT_NE(GBRP10BE,    GBRP10LE)\n#define AV_PIX_FMT_GBRP12    AV_PIX_FMT_NE(GBRP12BE,    GBRP12LE)\n#define AV_PIX_FMT_GBRP14    AV_PIX_FMT_NE(GBRP14BE,    GBRP14LE)\n#define AV_PIX_FMT_GBRP16    AV_PIX_FMT_NE(GBRP16BE,    GBRP16LE)\n#define AV_PIX_FMT_GBRAP10   AV_PIX_FMT_NE(GBRAP10BE,   GBRAP10LE)\n#define AV_PIX_FMT_GBRAP12   AV_PIX_FMT_NE(GBRAP12BE,   GBRAP12LE)\n#define AV_PIX_FMT_GBRAP16   AV_PIX_FMT_NE(GBRAP16BE,   GBRAP16LE)\n\n#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE,    BAYER_BGGR16LE)\n#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE,    BAYER_RGGB16LE)\n#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE,    BAYER_GBRG16LE)\n#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE,    BAYER_GRBG16LE)\n\n#define AV_PIX_FMT_GBRPF32    AV_PIX_FMT_NE(GBRPF32BE,  GBRPF32LE)\n#define AV_PIX_FMT_GBRAPF32   AV_PIX_FMT_NE(GBRAPF32BE, GBRAPF32LE)\n\n#define AV_PIX_FMT_GRAYF32    AV_PIX_FMT_NE(GRAYF32BE, GRAYF32LE)\n\n#define AV_PIX_FMT_YUVA420P9  AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE)\n#define AV_PIX_FMT_YUVA422P9  AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE)\n#define AV_PIX_FMT_YUVA444P9  AV_PIX_FMT_NE(YUVA444P9BE , YUVA444P9LE)\n#define AV_PIX_FMT_YUVA420P10 AV_PIX_FMT_NE(YUVA420P10BE, YUVA420P10LE)\n#define AV_PIX_FMT_YUVA422P10 AV_PIX_FMT_NE(YUVA422P10BE, YUVA422P10LE)\n#define AV_PIX_FMT_YUVA444P10 AV_PIX_FMT_NE(YUVA444P10BE, YUVA444P10LE)\n#define AV_PIX_FMT_YUVA422P12 AV_PIX_FMT_NE(YUVA422P12BE, YUVA422P12LE)\n#define AV_PIX_FMT_YUVA444P12 AV_PIX_FMT_NE(YUVA444P12BE, YUVA444P12LE)\n#define AV_PIX_FMT_YUVA420P16 AV_PIX_FMT_NE(YUVA420P16BE, YUVA420P16LE)\n#define AV_PIX_FMT_YUVA422P16 AV_PIX_FMT_NE(YUVA422P16BE, YUVA422P16LE)\n#define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE)\n\n#define AV_PIX_FMT_XYZ12      AV_PIX_FMT_NE(XYZ12BE, XYZ12LE)\n#define AV_PIX_FMT_NV20       AV_PIX_FMT_NE(NV20BE,  NV20LE)\n#define AV_PIX_FMT_AYUV64     AV_PIX_FMT_NE(AYUV64BE, AYUV64LE)\n#define AV_PIX_FMT_P010       AV_PIX_FMT_NE(P010BE,  P010LE)\n#define AV_PIX_FMT_P016       AV_PIX_FMT_NE(P016BE,  P016LE)\n\n#define AV_PIX_FMT_Y210       AV_PIX_FMT_NE(Y210BE,  Y210LE)\n#define AV_PIX_FMT_X2RGB10    AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE)\n#define AV_PIX_FMT_X2BGR10    AV_PIX_FMT_NE(X2BGR10BE, X2BGR10LE)\n\n#define AV_PIX_FMT_P210       AV_PIX_FMT_NE(P210BE, P210LE)\n#define AV_PIX_FMT_P410       AV_PIX_FMT_NE(P410BE, P410LE)\n#define AV_PIX_FMT_P216       AV_PIX_FMT_NE(P216BE, P216LE)\n#define AV_PIX_FMT_P416       AV_PIX_FMT_NE(P416BE, P416LE)\n\n/**\n  * Chromaticity coordinates of the source primaries.\n  * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.1 and ITU-T H.273.\n  */\nenum AVColorPrimaries {\n    AVCOL_PRI_RESERVED0   = 0,\n    AVCOL_PRI_BT709       = 1,  ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B\n    AVCOL_PRI_UNSPECIFIED = 2,\n    AVCOL_PRI_RESERVED    = 3,\n    AVCOL_PRI_BT470M      = 4,  ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)\n\n    AVCOL_PRI_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM\n    AVCOL_PRI_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC\n    AVCOL_PRI_SMPTE240M   = 7,  ///< identical to above, also called \"SMPTE C\" even though it uses D65\n    AVCOL_PRI_FILM        = 8,  ///< colour filters using Illuminant C\n    AVCOL_PRI_BT2020      = 9,  ///< ITU-R BT2020\n    AVCOL_PRI_SMPTE428    = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ)\n    AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428,\n    AVCOL_PRI_SMPTE431    = 11, ///< SMPTE ST 431-2 (2011) / DCI P3\n    AVCOL_PRI_SMPTE432    = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3\n    AVCOL_PRI_EBU3213     = 22, ///< EBU Tech. 3213-E (nothing there) / one of JEDEC P22 group phosphors\n    AVCOL_PRI_JEDEC_P22   = AVCOL_PRI_EBU3213,\n    AVCOL_PRI_NB                ///< Not part of ABI\n};\n\n/**\n * Color Transfer Characteristic.\n * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.2.\n */\nenum AVColorTransferCharacteristic {\n    AVCOL_TRC_RESERVED0    = 0,\n    AVCOL_TRC_BT709        = 1,  ///< also ITU-R BT1361\n    AVCOL_TRC_UNSPECIFIED  = 2,\n    AVCOL_TRC_RESERVED     = 3,\n    AVCOL_TRC_GAMMA22      = 4,  ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM\n    AVCOL_TRC_GAMMA28      = 5,  ///< also ITU-R BT470BG\n    AVCOL_TRC_SMPTE170M    = 6,  ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC\n    AVCOL_TRC_SMPTE240M    = 7,\n    AVCOL_TRC_LINEAR       = 8,  ///< \"Linear transfer characteristics\"\n    AVCOL_TRC_LOG          = 9,  ///< \"Logarithmic transfer characteristic (100:1 range)\"\n    AVCOL_TRC_LOG_SQRT     = 10, ///< \"Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)\"\n    AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4\n    AVCOL_TRC_BT1361_ECG   = 12, ///< ITU-R BT1361 Extended Colour Gamut\n    AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)\n    AVCOL_TRC_BT2020_10    = 14, ///< ITU-R BT2020 for 10-bit system\n    AVCOL_TRC_BT2020_12    = 15, ///< ITU-R BT2020 for 12-bit system\n    AVCOL_TRC_SMPTE2084    = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems\n    AVCOL_TRC_SMPTEST2084  = AVCOL_TRC_SMPTE2084,\n    AVCOL_TRC_SMPTE428     = 17, ///< SMPTE ST 428-1\n    AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,\n    AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as \"Hybrid log-gamma\"\n    AVCOL_TRC_NB                 ///< Not part of ABI\n};\n\n/**\n * YUV colorspace type.\n * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.3.\n */\nenum AVColorSpace {\n    AVCOL_SPC_RGB         = 0,  ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1\n    AVCOL_SPC_BT709       = 1,  ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B\n    AVCOL_SPC_UNSPECIFIED = 2,\n    AVCOL_SPC_RESERVED    = 3,  ///< reserved for future use by ITU-T and ISO/IEC just like 15-255 are\n    AVCOL_SPC_FCC         = 4,  ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)\n    AVCOL_SPC_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601\n    AVCOL_SPC_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above\n    AVCOL_SPC_SMPTE240M   = 7,  ///< derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries\n    AVCOL_SPC_YCGCO       = 8,  ///< used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16\n    AVCOL_SPC_YCOCG       = AVCOL_SPC_YCGCO,\n    AVCOL_SPC_BT2020_NCL  = 9,  ///< ITU-R BT2020 non-constant luminance system\n    AVCOL_SPC_BT2020_CL   = 10, ///< ITU-R BT2020 constant luminance system\n    AVCOL_SPC_SMPTE2085   = 11, ///< SMPTE 2085, Y'D'zD'x\n    AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system\n    AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system\n    AVCOL_SPC_ICTCP       = 14, ///< ITU-R BT.2100-0, ICtCp\n    AVCOL_SPC_NB                ///< Not part of ABI\n};\n\n/**\n * Visual content value range.\n *\n * These values are based on definitions that can be found in multiple\n * specifications, such as ITU-T BT.709 (3.4 - Quantization of RGB, luminance\n * and colour-difference signals), ITU-T BT.2020 (Table 5 - Digital\n * Representation) as well as ITU-T BT.2100 (Table 9 - Digital 10- and 12-bit\n * integer representation). At the time of writing, the BT.2100 one is\n * recommended, as it also defines the full range representation.\n *\n * Common definitions:\n *   - For RGB and luma planes such as Y in YCbCr and I in ICtCp,\n *     'E' is the original value in range of 0.0 to 1.0.\n *   - For chroma planes such as Cb,Cr and Ct,Cp, 'E' is the original\n *     value in range of -0.5 to 0.5.\n *   - 'n' is the output bit depth.\n *   - For additional definitions such as rounding and clipping to valid n\n *     bit unsigned integer range, please refer to BT.2100 (Table 9).\n */\nenum AVColorRange {\n    AVCOL_RANGE_UNSPECIFIED = 0,\n\n    /**\n     * Narrow or limited range content.\n     *\n     * - For luma planes:\n     *\n     *       (219 * E + 16) * 2^(n-8)\n     *\n     *   F.ex. the range of 16-235 for 8 bits\n     *\n     * - For chroma planes:\n     *\n     *       (224 * E + 128) * 2^(n-8)\n     *\n     *   F.ex. the range of 16-240 for 8 bits\n     */\n    AVCOL_RANGE_MPEG        = 1,\n\n    /**\n     * Full range content.\n     *\n     * - For RGB and luma planes:\n     *\n     *       (2^n - 1) * E\n     *\n     *   F.ex. the range of 0-255 for 8 bits\n     *\n     * - For chroma planes:\n     *\n     *       (2^n - 1) * E + 2^(n - 1)\n     *\n     *   F.ex. the range of 1-255 for 8 bits\n     */\n    AVCOL_RANGE_JPEG        = 2,\n    AVCOL_RANGE_NB               ///< Not part of ABI\n};\n\n/**\n * Location of chroma samples.\n *\n * Illustration showing the location of the first (top left) chroma sample of the\n * image, the left shows only luma, the right\n * shows the location of the chroma sample, the 2 could be imagined to overlay\n * each other but are drawn separately due to limitations of ASCII\n *\n *                1st 2nd       1st 2nd horizontal luma sample positions\n *                 v   v         v   v\n *                 ______        ______\n *1st luma line > |X   X ...    |3 4 X ...     X are luma samples,\n *                |             |1 2           1-6 are possible chroma positions\n *2nd luma line > |X   X ...    |5 6 X ...     0 is undefined/unknown position\n */\nenum AVChromaLocation {\n    AVCHROMA_LOC_UNSPECIFIED = 0,\n    AVCHROMA_LOC_LEFT        = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0\n    AVCHROMA_LOC_CENTER      = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0\n    AVCHROMA_LOC_TOPLEFT     = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2\n    AVCHROMA_LOC_TOP         = 4,\n    AVCHROMA_LOC_BOTTOMLEFT  = 5,\n    AVCHROMA_LOC_BOTTOM      = 6,\n    AVCHROMA_LOC_NB               ///< Not part of ABI\n};\n\n#endif /* AVUTIL_PIXFMT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/random_seed.h",
    "content": "/*\n * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_RANDOM_SEED_H\n#define AVUTIL_RANDOM_SEED_H\n\n#include <stdint.h>\n/**\n * @addtogroup lavu_crypto\n * @{\n */\n\n/**\n * Get a seed to use in conjunction with random functions.\n * This function tries to provide a good seed at a best effort bases.\n * Its possible to call this function multiple times if more bits are needed.\n * It can be quite slow, which is why it should only be used as seed for a faster\n * PRNG. The quality of the seed depends on the platform.\n */\nuint32_t av_get_random_seed(void);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_RANDOM_SEED_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/rational.h",
    "content": "/*\n * rational numbers\n * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_math_rational\n * Utilties for rational number calculation.\n * @author Michael Niedermayer <michaelni@gmx.at>\n */\n\n#ifndef AVUTIL_RATIONAL_H\n#define AVUTIL_RATIONAL_H\n\n#include <stdint.h>\n#include <limits.h>\n#include \"attributes.h\"\n\n/**\n * @defgroup lavu_math_rational AVRational\n * @ingroup lavu_math\n * Rational number calculation.\n *\n * While rational numbers can be expressed as floating-point numbers, the\n * conversion process is a lossy one, so are floating-point operations. On the\n * other hand, the nature of FFmpeg demands highly accurate calculation of\n * timestamps. This set of rational number utilities serves as a generic\n * interface for manipulating rational numbers as pairs of numerators and\n * denominators.\n *\n * Many of the functions that operate on AVRational's have the suffix `_q`, in\n * reference to the mathematical symbol \"ℚ\" (Q) which denotes the set of all\n * rational numbers.\n *\n * @{\n */\n\n/**\n * Rational number (pair of numerator and denominator).\n */\ntypedef struct AVRational{\n    int num; ///< Numerator\n    int den; ///< Denominator\n} AVRational;\n\n/**\n * Create an AVRational.\n *\n * Useful for compilers that do not support compound literals.\n *\n * @note The return value is not reduced.\n * @see av_reduce()\n */\nstatic inline AVRational av_make_q(int num, int den)\n{\n    AVRational r = { num, den };\n    return r;\n}\n\n/**\n * Compare two rationals.\n *\n * @param a First rational\n * @param b Second rational\n *\n * @return One of the following values:\n *         - 0 if `a == b`\n *         - 1 if `a > b`\n *         - -1 if `a < b`\n *         - `INT_MIN` if one of the values is of the form `0 / 0`\n */\nstatic inline int av_cmp_q(AVRational a, AVRational b){\n    const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;\n\n    if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1;\n    else if(b.den && a.den) return 0;\n    else if(a.num && b.num) return (a.num>>31) - (b.num>>31);\n    else                    return INT_MIN;\n}\n\n/**\n * Convert an AVRational to a `double`.\n * @param a AVRational to convert\n * @return `a` in floating-point form\n * @see av_d2q()\n */\nstatic inline double av_q2d(AVRational a){\n    return a.num / (double) a.den;\n}\n\n/**\n * Reduce a fraction.\n *\n * This is useful for framerate calculations.\n *\n * @param[out] dst_num Destination numerator\n * @param[out] dst_den Destination denominator\n * @param[in]      num Source numerator\n * @param[in]      den Source denominator\n * @param[in]      max Maximum allowed values for `dst_num` & `dst_den`\n * @return 1 if the operation is exact, 0 otherwise\n */\nint av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max);\n\n/**\n * Multiply two rationals.\n * @param b First rational\n * @param c Second rational\n * @return b*c\n */\nAVRational av_mul_q(AVRational b, AVRational c) av_const;\n\n/**\n * Divide one rational by another.\n * @param b First rational\n * @param c Second rational\n * @return b/c\n */\nAVRational av_div_q(AVRational b, AVRational c) av_const;\n\n/**\n * Add two rationals.\n * @param b First rational\n * @param c Second rational\n * @return b+c\n */\nAVRational av_add_q(AVRational b, AVRational c) av_const;\n\n/**\n * Subtract one rational from another.\n * @param b First rational\n * @param c Second rational\n * @return b-c\n */\nAVRational av_sub_q(AVRational b, AVRational c) av_const;\n\n/**\n * Invert a rational.\n * @param q value\n * @return 1 / q\n */\nstatic av_always_inline AVRational av_inv_q(AVRational q)\n{\n    AVRational r = { q.den, q.num };\n    return r;\n}\n\n/**\n * Convert a double precision floating point number to a rational.\n *\n * In case of infinity, the returned value is expressed as `{1, 0}` or\n * `{-1, 0}` depending on the sign.\n *\n * @param d   `double` to convert\n * @param max Maximum allowed numerator and denominator\n * @return `d` in AVRational form\n * @see av_q2d()\n */\nAVRational av_d2q(double d, int max) av_const;\n\n/**\n * Find which of the two rationals is closer to another rational.\n *\n * @param q     Rational to be compared against\n * @param q1,q2 Rationals to be tested\n * @return One of the following values:\n *         - 1 if `q1` is nearer to `q` than `q2`\n *         - -1 if `q2` is nearer to `q` than `q1`\n *         - 0 if they have the same distance\n */\nint av_nearer_q(AVRational q, AVRational q1, AVRational q2);\n\n/**\n * Find the value in a list of rationals nearest a given reference rational.\n *\n * @param q      Reference rational\n * @param q_list Array of rationals terminated by `{0, 0}`\n * @return Index of the nearest value found in the array\n */\nint av_find_nearest_q_idx(AVRational q, const AVRational* q_list);\n\n/**\n * Convert an AVRational to a IEEE 32-bit `float` expressed in fixed-point\n * format.\n *\n * @param q Rational to be converted\n * @return Equivalent floating-point value, expressed as an unsigned 32-bit\n *         integer.\n * @note The returned value is platform-indepedant.\n */\nuint32_t av_q2intfloat(AVRational q);\n\n/**\n * Return the best rational so that a and b are multiple of it.\n * If the resulting denominator is larger than max_den, return def.\n */\nAVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_RATIONAL_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/rc4.h",
    "content": "/*\n * RC4 encryption/decryption/pseudo-random number generator\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_RC4_H\n#define AVUTIL_RC4_H\n\n#include <stdint.h>\n\n/**\n * @defgroup lavu_rc4 RC4\n * @ingroup lavu_crypto\n * @{\n */\n\ntypedef struct AVRC4 {\n    uint8_t state[256];\n    int x, y;\n} AVRC4;\n\n/**\n * Allocate an AVRC4 context.\n */\nAVRC4 *av_rc4_alloc(void);\n\n/**\n * @brief Initializes an AVRC4 context.\n *\n * @param key_bits must be a multiple of 8\n * @param decrypt 0 for encryption, 1 for decryption, currently has no effect\n * @return zero on success, negative value otherwise\n */\nint av_rc4_init(struct AVRC4 *d, const uint8_t *key, int key_bits, int decrypt);\n\n/**\n * @brief Encrypts / decrypts using the RC4 algorithm.\n *\n * @param count number of bytes\n * @param dst destination array, can be equal to src\n * @param src source array, can be equal to dst, may be NULL\n * @param iv not (yet) used for RC4, should be NULL\n * @param decrypt 0 for encryption, 1 for decryption, not (yet) used\n */\nvoid av_rc4_crypt(struct AVRC4 *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_RC4_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/replaygain.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_REPLAYGAIN_H\n#define AVUTIL_REPLAYGAIN_H\n\n#include <stdint.h>\n\n/**\n * ReplayGain information (see\n * http://wiki.hydrogenaudio.org/index.php?title=ReplayGain_1.0_specification).\n * The size of this struct is a part of the public ABI.\n */\ntypedef struct AVReplayGain {\n    /**\n     * Track replay gain in microbels (divide by 100000 to get the value in dB).\n     * Should be set to INT32_MIN when unknown.\n     */\n    int32_t track_gain;\n    /**\n     * Peak track amplitude, with 100000 representing full scale (but values\n     * may overflow). 0 when unknown.\n     */\n    uint32_t track_peak;\n    /**\n     * Same as track_gain, but for the whole album.\n     */\n    int32_t album_gain;\n    /**\n     * Same as track_peak, but for the whole album,\n     */\n    uint32_t album_peak;\n} AVReplayGain;\n\n#endif /* AVUTIL_REPLAYGAIN_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/ripemd.h",
    "content": "/*\n * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>\n * Copyright (C) 2013 James Almer <jamrial@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_ripemd\n * Public header for RIPEMD hash function implementation.\n */\n\n#ifndef AVUTIL_RIPEMD_H\n#define AVUTIL_RIPEMD_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"attributes.h\"\n\n/**\n * @defgroup lavu_ripemd RIPEMD\n * @ingroup lavu_hash\n * RIPEMD hash function implementation.\n *\n * @{\n */\n\nextern const int av_ripemd_size;\n\nstruct AVRIPEMD;\n\n/**\n * Allocate an AVRIPEMD context.\n */\nstruct AVRIPEMD *av_ripemd_alloc(void);\n\n/**\n * Initialize RIPEMD hashing.\n *\n * @param context pointer to the function context (of size av_ripemd_size)\n * @param bits    number of bits in digest (128, 160, 256 or 320 bits)\n * @return        zero if initialization succeeded, -1 otherwise\n */\nint av_ripemd_init(struct AVRIPEMD* context, int bits);\n\n/**\n * Update hash value.\n *\n * @param context hash function context\n * @param data    input data to update hash with\n * @param len     input data length\n */\nvoid av_ripemd_update(struct AVRIPEMD* context, const uint8_t* data, size_t len);\n\n/**\n * Finish hashing and output digest value.\n *\n * @param context hash function context\n * @param digest  buffer where output digest value is stored\n */\nvoid av_ripemd_final(struct AVRIPEMD* context, uint8_t *digest);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_RIPEMD_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/samplefmt.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_SAMPLEFMT_H\n#define AVUTIL_SAMPLEFMT_H\n\n#include <stdint.h>\n\n/**\n * @addtogroup lavu_audio\n * @{\n *\n * @defgroup lavu_sampfmts Audio sample formats\n *\n * Audio sample format enumeration and related convenience functions.\n * @{\n */\n\n/**\n * Audio sample formats\n *\n * - The data described by the sample format is always in native-endian order.\n *   Sample values can be expressed by native C types, hence the lack of a signed\n *   24-bit sample format even though it is a common raw audio data format.\n *\n * - The floating-point formats are based on full volume being in the range\n *   [-1.0, 1.0]. Any values outside this range are beyond full volume level.\n *\n * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg\n *   (such as AVFrame in libavcodec) is as follows:\n *\n * @par\n * For planar sample formats, each audio channel is in a separate data plane,\n * and linesize is the buffer size, in bytes, for a single plane. All data\n * planes must be the same size. For packed sample formats, only the first data\n * plane is used, and samples for each channel are interleaved. In this case,\n * linesize is the buffer size, in bytes, for the 1 plane.\n *\n */\nenum AVSampleFormat {\n    AV_SAMPLE_FMT_NONE = -1,\n    AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits\n    AV_SAMPLE_FMT_S16,         ///< signed 16 bits\n    AV_SAMPLE_FMT_S32,         ///< signed 32 bits\n    AV_SAMPLE_FMT_FLT,         ///< float\n    AV_SAMPLE_FMT_DBL,         ///< double\n\n    AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar\n    AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar\n    AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar\n    AV_SAMPLE_FMT_FLTP,        ///< float, planar\n    AV_SAMPLE_FMT_DBLP,        ///< double, planar\n    AV_SAMPLE_FMT_S64,         ///< signed 64 bits\n    AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar\n\n    AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically\n};\n\n/**\n * Return the name of sample_fmt, or NULL if sample_fmt is not\n * recognized.\n */\nconst char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt);\n\n/**\n * Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE\n * on error.\n */\nenum AVSampleFormat av_get_sample_fmt(const char *name);\n\n/**\n * Return the planar<->packed alternative form of the given sample format, or\n * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the\n * requested planar/packed format, the format returned is the same as the\n * input.\n */\nenum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar);\n\n/**\n * Get the packed alternative form of the given sample format.\n *\n * If the passed sample_fmt is already in packed format, the format returned is\n * the same as the input.\n *\n * @return  the packed alternative form of the given sample format or\n            AV_SAMPLE_FMT_NONE on error.\n */\nenum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt);\n\n/**\n * Get the planar alternative form of the given sample format.\n *\n * If the passed sample_fmt is already in planar format, the format returned is\n * the same as the input.\n *\n * @return  the planar alternative form of the given sample format or\n            AV_SAMPLE_FMT_NONE on error.\n */\nenum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt);\n\n/**\n * Generate a string corresponding to the sample format with\n * sample_fmt, or a header if sample_fmt is negative.\n *\n * @param buf the buffer where to write the string\n * @param buf_size the size of buf\n * @param sample_fmt the number of the sample format to print the\n * corresponding info string, or a negative value to print the\n * corresponding header.\n * @return the pointer to the filled buffer or NULL if sample_fmt is\n * unknown or in case of other errors\n */\nchar *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt);\n\n/**\n * Return number of bytes per sample.\n *\n * @param sample_fmt the sample format\n * @return number of bytes per sample or zero if unknown for the given\n * sample format\n */\nint av_get_bytes_per_sample(enum AVSampleFormat sample_fmt);\n\n/**\n * Check if the sample format is planar.\n *\n * @param sample_fmt the sample format to inspect\n * @return 1 if the sample format is planar, 0 if it is interleaved\n */\nint av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt);\n\n/**\n * Get the required buffer size for the given audio parameters.\n *\n * @param[out] linesize calculated linesize, may be NULL\n * @param nb_channels   the number of channels\n * @param nb_samples    the number of samples in a single channel\n * @param sample_fmt    the sample format\n * @param align         buffer size alignment (0 = default, 1 = no alignment)\n * @return              required buffer size, or negative error code on failure\n */\nint av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,\n                               enum AVSampleFormat sample_fmt, int align);\n\n/**\n * @}\n *\n * @defgroup lavu_sampmanip Samples manipulation\n *\n * Functions that manipulate audio samples\n * @{\n */\n\n/**\n * Fill plane data pointers and linesize for samples with sample\n * format sample_fmt.\n *\n * The audio_data array is filled with the pointers to the samples data planes:\n * for planar, set the start point of each channel's data within the buffer,\n * for packed, set the start point of the entire buffer only.\n *\n * The value pointed to by linesize is set to the aligned size of each\n * channel's data buffer for planar layout, or to the aligned size of the\n * buffer for all channels for packed layout.\n *\n * The buffer in buf must be big enough to contain all the samples\n * (use av_samples_get_buffer_size() to compute its minimum size),\n * otherwise the audio_data pointers will point to invalid data.\n *\n * @see enum AVSampleFormat\n * The documentation for AVSampleFormat describes the data layout.\n *\n * @param[out] audio_data  array to be filled with the pointer for each channel\n * @param[out] linesize    calculated linesize, may be NULL\n * @param buf              the pointer to a buffer containing the samples\n * @param nb_channels      the number of channels\n * @param nb_samples       the number of samples in a single channel\n * @param sample_fmt       the sample format\n * @param align            buffer size alignment (0 = default, 1 = no alignment)\n * @return                 minimum size in bytes required for the buffer on success,\n *                         or a negative error code on failure\n */\nint av_samples_fill_arrays(uint8_t **audio_data, int *linesize,\n                           const uint8_t *buf,\n                           int nb_channels, int nb_samples,\n                           enum AVSampleFormat sample_fmt, int align);\n\n/**\n * Allocate a samples buffer for nb_samples samples, and fill data pointers and\n * linesize accordingly.\n * The allocated samples buffer can be freed by using av_freep(&audio_data[0])\n * Allocated data will be initialized to silence.\n *\n * @see enum AVSampleFormat\n * The documentation for AVSampleFormat describes the data layout.\n *\n * @param[out] audio_data  array to be filled with the pointer for each channel\n * @param[out] linesize    aligned size for audio buffer(s), may be NULL\n * @param nb_channels      number of audio channels\n * @param nb_samples       number of samples per channel\n * @param align            buffer size alignment (0 = default, 1 = no alignment)\n * @return                 >=0 on success or a negative error code on failure\n * @todo return the size of the allocated buffer in case of success at the next bump\n * @see av_samples_fill_arrays()\n * @see av_samples_alloc_array_and_samples()\n */\nint av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels,\n                     int nb_samples, enum AVSampleFormat sample_fmt, int align);\n\n/**\n * Allocate a data pointers array, samples buffer for nb_samples\n * samples, and fill data pointers and linesize accordingly.\n *\n * This is the same as av_samples_alloc(), but also allocates the data\n * pointers array.\n *\n * @see av_samples_alloc()\n */\nint av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels,\n                                       int nb_samples, enum AVSampleFormat sample_fmt, int align);\n\n/**\n * Copy samples from src to dst.\n *\n * @param dst destination array of pointers to data planes\n * @param src source array of pointers to data planes\n * @param dst_offset offset in samples at which the data will be written to dst\n * @param src_offset offset in samples at which the data will be read from src\n * @param nb_samples number of samples to be copied\n * @param nb_channels number of audio channels\n * @param sample_fmt audio sample format\n */\nint av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset,\n                    int src_offset, int nb_samples, int nb_channels,\n                    enum AVSampleFormat sample_fmt);\n\n/**\n * Fill an audio buffer with silence.\n *\n * @param audio_data  array of pointers to data planes\n * @param offset      offset in samples at which to start filling\n * @param nb_samples  number of samples to fill\n * @param nb_channels number of audio channels\n * @param sample_fmt  audio sample format\n */\nint av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples,\n                           int nb_channels, enum AVSampleFormat sample_fmt);\n\n/**\n * @}\n * @}\n */\n#endif /* AVUTIL_SAMPLEFMT_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/sha.h",
    "content": "/*\n * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_sha\n * Public header for SHA-1 & SHA-256 hash function implementations.\n */\n\n#ifndef AVUTIL_SHA_H\n#define AVUTIL_SHA_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"attributes.h\"\n\n/**\n * @defgroup lavu_sha SHA\n * @ingroup lavu_hash\n * SHA-1 and SHA-256 (Secure Hash Algorithm) hash function implementations.\n *\n * This module supports the following SHA hash functions:\n *\n * - SHA-1: 160 bits\n * - SHA-224: 224 bits, as a variant of SHA-2\n * - SHA-256: 256 bits, as a variant of SHA-2\n *\n * @see For SHA-384, SHA-512, and variants thereof, see @ref lavu_sha512.\n *\n * @{\n */\n\nextern const int av_sha_size;\n\nstruct AVSHA;\n\n/**\n * Allocate an AVSHA context.\n */\nstruct AVSHA *av_sha_alloc(void);\n\n/**\n * Initialize SHA-1 or SHA-2 hashing.\n *\n * @param context pointer to the function context (of size av_sha_size)\n * @param bits    number of bits in digest (SHA-1 - 160 bits, SHA-2 224 or 256 bits)\n * @return        zero if initialization succeeded, -1 otherwise\n */\nint av_sha_init(struct AVSHA* context, int bits);\n\n/**\n * Update hash value.\n *\n * @param ctx     hash function context\n * @param data    input data to update hash with\n * @param len     input data length\n */\nvoid av_sha_update(struct AVSHA *ctx, const uint8_t *data, size_t len);\n\n/**\n * Finish hashing and output digest value.\n *\n * @param context hash function context\n * @param digest  buffer where output digest value is stored\n */\nvoid av_sha_final(struct AVSHA* context, uint8_t *digest);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_SHA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/sha512.h",
    "content": "/*\n * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>\n * Copyright (C) 2013 James Almer <jamrial@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu_sha512\n * Public header for SHA-512 implementation.\n */\n\n#ifndef AVUTIL_SHA512_H\n#define AVUTIL_SHA512_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"attributes.h\"\n\n/**\n * @defgroup lavu_sha512 SHA-512\n * @ingroup lavu_hash\n * SHA-512 (Secure Hash Algorithm) hash function implementations.\n *\n * This module supports the following SHA-2 hash functions:\n *\n * - SHA-512/224: 224 bits\n * - SHA-512/256: 256 bits\n * - SHA-384: 384 bits\n * - SHA-512: 512 bits\n *\n * @see For SHA-1, SHA-256, and variants thereof, see @ref lavu_sha.\n *\n * @{\n */\n\nextern const int av_sha512_size;\n\nstruct AVSHA512;\n\n/**\n * Allocate an AVSHA512 context.\n */\nstruct AVSHA512 *av_sha512_alloc(void);\n\n/**\n * Initialize SHA-2 512 hashing.\n *\n * @param context pointer to the function context (of size av_sha512_size)\n * @param bits    number of bits in digest (224, 256, 384 or 512 bits)\n * @return        zero if initialization succeeded, -1 otherwise\n */\nint av_sha512_init(struct AVSHA512* context, int bits);\n\n/**\n * Update hash value.\n *\n * @param context hash function context\n * @param data    input data to update hash with\n * @param len     input data length\n */\nvoid av_sha512_update(struct AVSHA512* context, const uint8_t* data, size_t len);\n\n/**\n * Finish hashing and output digest value.\n *\n * @param context hash function context\n * @param digest  buffer where output digest value is stored\n */\nvoid av_sha512_final(struct AVSHA512* context, uint8_t *digest);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_SHA512_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/spherical.h",
    "content": "/*\n * Copyright (c) 2016 Vittorio Giovara <vittorio.giovara@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * Spherical video\n */\n\n#ifndef AVUTIL_SPHERICAL_H\n#define AVUTIL_SPHERICAL_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n/**\n * @addtogroup lavu_video\n * @{\n *\n * @defgroup lavu_video_spherical Spherical video mapping\n * @{\n */\n\n/**\n * @addtogroup lavu_video_spherical\n * A spherical video file contains surfaces that need to be mapped onto a\n * sphere. Depending on how the frame was converted, a different distortion\n * transformation or surface recomposition function needs to be applied before\n * the video should be mapped and displayed.\n */\n\n/**\n * Projection of the video surface(s) on a sphere.\n */\nenum AVSphericalProjection {\n    /**\n     * Video represents a sphere mapped on a flat surface using\n     * equirectangular projection.\n     */\n    AV_SPHERICAL_EQUIRECTANGULAR,\n\n    /**\n     * Video frame is split into 6 faces of a cube, and arranged on a\n     * 3x2 layout. Faces are oriented upwards for the front, left, right,\n     * and back faces. The up face is oriented so the top of the face is\n     * forwards and the down face is oriented so the top of the face is\n     * to the back.\n     */\n    AV_SPHERICAL_CUBEMAP,\n\n    /**\n     * Video represents a portion of a sphere mapped on a flat surface\n     * using equirectangular projection. The @ref bounding fields indicate\n     * the position of the current video in a larger surface.\n     */\n    AV_SPHERICAL_EQUIRECTANGULAR_TILE,\n};\n\n/**\n * This structure describes how to handle spherical videos, outlining\n * information about projection, initial layout, and any other view modifier.\n *\n * @note The struct must be allocated with av_spherical_alloc() and\n *       its size is not a part of the public ABI.\n */\ntypedef struct AVSphericalMapping {\n    /**\n     * Projection type.\n     */\n    enum AVSphericalProjection projection;\n\n    /**\n     * @name Initial orientation\n     * @{\n     * There fields describe additional rotations applied to the sphere after\n     * the video frame is mapped onto it. The sphere is rotated around the\n     * viewer, who remains stationary. The order of transformation is always\n     * yaw, followed by pitch, and finally by roll.\n     *\n     * The coordinate system matches the one defined in OpenGL, where the\n     * forward vector (z) is coming out of screen, and it is equivalent to\n     * a rotation matrix of R = r_y(yaw) * r_x(pitch) * r_z(roll).\n     *\n     * A positive yaw rotates the portion of the sphere in front of the viewer\n     * toward their right. A positive pitch rotates the portion of the sphere\n     * in front of the viewer upwards. A positive roll tilts the portion of\n     * the sphere in front of the viewer to the viewer's right.\n     *\n     * These values are exported as 16.16 fixed point.\n     *\n     * See this equirectangular projection as example:\n     *\n     * @code{.unparsed}\n     *                   Yaw\n     *     -180           0           180\n     *   90 +-------------+-------------+  180\n     *      |             |             |                  up\n     * P    |             |             |                 y|    forward\n     * i    |             ^             |                  |   /z\n     * t  0 +-------------X-------------+    0 Roll        |  /\n     * c    |             |             |                  | /\n     * h    |             |             |                 0|/_____right\n     *      |             |             |                        x\n     *  -90 +-------------+-------------+ -180\n     *\n     * X - the default camera center\n     * ^ - the default up vector\n     * @endcode\n     */\n    int32_t yaw;   ///< Rotation around the up vector [-180, 180].\n    int32_t pitch; ///< Rotation around the right vector [-90, 90].\n    int32_t roll;  ///< Rotation around the forward vector [-180, 180].\n    /**\n     * @}\n     */\n\n    /**\n     * @name Bounding rectangle\n     * @anchor bounding\n     * @{\n     * These fields indicate the location of the current tile, and where\n     * it should be mapped relative to the original surface. They are\n     * exported as 0.32 fixed point, and can be converted to classic\n     * pixel values with av_spherical_bounds().\n     *\n     * @code{.unparsed}\n     *      +----------------+----------+\n     *      |                |bound_top |\n     *      |            +--------+     |\n     *      | bound_left |tile    |     |\n     *      +<---------->|        |<--->+bound_right\n     *      |            +--------+     |\n     *      |                |          |\n     *      |    bound_bottom|          |\n     *      +----------------+----------+\n     * @endcode\n     *\n     * If needed, the original video surface dimensions can be derived\n     * by adding the current stream or frame size to the related bounds,\n     * like in the following example:\n     *\n     * @code{c}\n     *     original_width  = tile->width  + bound_left + bound_right;\n     *     original_height = tile->height + bound_top  + bound_bottom;\n     * @endcode\n     *\n     * @note These values are valid only for the tiled equirectangular\n     *       projection type (@ref AV_SPHERICAL_EQUIRECTANGULAR_TILE),\n     *       and should be ignored in all other cases.\n     */\n    uint32_t bound_left;   ///< Distance from the left edge\n    uint32_t bound_top;    ///< Distance from the top edge\n    uint32_t bound_right;  ///< Distance from the right edge\n    uint32_t bound_bottom; ///< Distance from the bottom edge\n    /**\n     * @}\n     */\n\n    /**\n     * Number of pixels to pad from the edge of each cube face.\n     *\n     * @note This value is valid for only for the cubemap projection type\n     *       (@ref AV_SPHERICAL_CUBEMAP), and should be ignored in all other\n     *       cases.\n     */\n    uint32_t padding;\n} AVSphericalMapping;\n\n/**\n * Allocate a AVSphericalVideo structure and initialize its fields to default\n * values.\n *\n * @return the newly allocated struct or NULL on failure\n */\nAVSphericalMapping *av_spherical_alloc(size_t *size);\n\n/**\n * Convert the @ref bounding fields from an AVSphericalVideo\n * from 0.32 fixed point to pixels.\n *\n * @param map    The AVSphericalVideo map to read bound values from.\n * @param width  Width of the current frame or stream.\n * @param height Height of the current frame or stream.\n * @param left   Pixels from the left edge.\n * @param top    Pixels from the top edge.\n * @param right  Pixels from the right edge.\n * @param bottom Pixels from the bottom edge.\n */\nvoid av_spherical_tile_bounds(const AVSphericalMapping *map,\n                              size_t width, size_t height,\n                              size_t *left, size_t *top,\n                              size_t *right, size_t *bottom);\n\n/**\n * Provide a human-readable name of a given AVSphericalProjection.\n *\n * @param projection The input AVSphericalProjection.\n *\n * @return The name of the AVSphericalProjection, or \"unknown\".\n */\nconst char *av_spherical_projection_name(enum AVSphericalProjection projection);\n\n/**\n * Get the AVSphericalProjection form a human-readable name.\n *\n * @param name The input string.\n *\n * @return The AVSphericalProjection value, or -1 if not found.\n */\nint av_spherical_from_name(const char *name);\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_SPHERICAL_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/stereo3d.h",
    "content": "/*\n * Copyright (c) 2013 Vittorio Giovara <vittorio.giovara@gmail.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * Stereoscopic video\n */\n\n#ifndef AVUTIL_STEREO3D_H\n#define AVUTIL_STEREO3D_H\n\n#include <stdint.h>\n\n#include \"frame.h\"\n\n/**\n * @addtogroup lavu_video\n * @{\n *\n * @defgroup lavu_video_stereo3d Stereo3D types and functions\n * @{\n */\n\n/**\n * @addtogroup lavu_video_stereo3d\n * A stereoscopic video file consists in multiple views embedded in a single\n * frame, usually describing two views of a scene. This file describes all\n * possible codec-independent view arrangements.\n * */\n\n/**\n * List of possible 3D Types\n */\nenum AVStereo3DType {\n    /**\n     * Video is not stereoscopic (and metadata has to be there).\n     */\n    AV_STEREO3D_2D,\n\n    /**\n     * Views are next to each other.\n     *\n     * @code{.unparsed}\n     *    LLLLRRRR\n     *    LLLLRRRR\n     *    LLLLRRRR\n     *    ...\n     * @endcode\n     */\n    AV_STEREO3D_SIDEBYSIDE,\n\n    /**\n     * Views are on top of each other.\n     *\n     * @code{.unparsed}\n     *    LLLLLLLL\n     *    LLLLLLLL\n     *    RRRRRRRR\n     *    RRRRRRRR\n     * @endcode\n     */\n    AV_STEREO3D_TOPBOTTOM,\n\n    /**\n     * Views are alternated temporally.\n     *\n     * @code{.unparsed}\n     *     frame0   frame1   frame2   ...\n     *    LLLLLLLL RRRRRRRR LLLLLLLL\n     *    LLLLLLLL RRRRRRRR LLLLLLLL\n     *    LLLLLLLL RRRRRRRR LLLLLLLL\n     *    ...      ...      ...\n     * @endcode\n     */\n    AV_STEREO3D_FRAMESEQUENCE,\n\n    /**\n     * Views are packed in a checkerboard-like structure per pixel.\n     *\n     * @code{.unparsed}\n     *    LRLRLRLR\n     *    RLRLRLRL\n     *    LRLRLRLR\n     *    ...\n     * @endcode\n     */\n    AV_STEREO3D_CHECKERBOARD,\n\n    /**\n     * Views are next to each other, but when upscaling\n     * apply a checkerboard pattern.\n     *\n     * @code{.unparsed}\n     *     LLLLRRRR          L L L L    R R R R\n     *     LLLLRRRR    =>     L L L L  R R R R\n     *     LLLLRRRR          L L L L    R R R R\n     *     LLLLRRRR           L L L L  R R R R\n     * @endcode\n     */\n    AV_STEREO3D_SIDEBYSIDE_QUINCUNX,\n\n    /**\n     * Views are packed per line, as if interlaced.\n     *\n     * @code{.unparsed}\n     *    LLLLLLLL\n     *    RRRRRRRR\n     *    LLLLLLLL\n     *    ...\n     * @endcode\n     */\n    AV_STEREO3D_LINES,\n\n    /**\n     * Views are packed per column.\n     *\n     * @code{.unparsed}\n     *    LRLRLRLR\n     *    LRLRLRLR\n     *    LRLRLRLR\n     *    ...\n     * @endcode\n     */\n    AV_STEREO3D_COLUMNS,\n};\n\n/**\n * List of possible view types.\n */\nenum AVStereo3DView {\n    /**\n     * Frame contains two packed views.\n     */\n    AV_STEREO3D_VIEW_PACKED,\n\n    /**\n     * Frame contains only the left view.\n     */\n    AV_STEREO3D_VIEW_LEFT,\n\n    /**\n     * Frame contains only the right view.\n     */\n    AV_STEREO3D_VIEW_RIGHT,\n};\n\n/**\n * Inverted views, Right/Bottom represents the left view.\n */\n#define AV_STEREO3D_FLAG_INVERT     (1 << 0)\n\n/**\n * Stereo 3D type: this structure describes how two videos are packed\n * within a single video surface, with additional information as needed.\n *\n * @note The struct must be allocated with av_stereo3d_alloc() and\n *       its size is not a part of the public ABI.\n */\ntypedef struct AVStereo3D {\n    /**\n     * How views are packed within the video.\n     */\n    enum AVStereo3DType type;\n\n    /**\n     * Additional information about the frame packing.\n     */\n    int flags;\n\n    /**\n     * Determines which views are packed.\n     */\n    enum AVStereo3DView view;\n} AVStereo3D;\n\n/**\n * Allocate an AVStereo3D structure and set its fields to default values.\n * The resulting struct can be freed using av_freep().\n *\n * @return An AVStereo3D filled with default values or NULL on failure.\n */\nAVStereo3D *av_stereo3d_alloc(void);\n\n/**\n * Allocate a complete AVFrameSideData and add it to the frame.\n *\n * @param frame The frame which side data is added to.\n *\n * @return The AVStereo3D structure to be filled by caller.\n */\nAVStereo3D *av_stereo3d_create_side_data(AVFrame *frame);\n\n/**\n * Provide a human-readable name of a given stereo3d type.\n *\n * @param type The input stereo3d type value.\n *\n * @return The name of the stereo3d value, or \"unknown\".\n */\nconst char *av_stereo3d_type_name(unsigned int type);\n\n/**\n * Get the AVStereo3DType form a human-readable name.\n *\n * @param name The input string.\n *\n * @return The AVStereo3DType value, or -1 if not found.\n */\nint av_stereo3d_from_name(const char *name);\n\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_STEREO3D_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/tea.h",
    "content": "/*\n * A 32-bit implementation of the TEA algorithm\n * Copyright (c) 2015 Vesselin Bontchev\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_TEA_H\n#define AVUTIL_TEA_H\n\n#include <stdint.h>\n\n/**\n * @file\n * @brief Public header for libavutil TEA algorithm\n * @defgroup lavu_tea TEA\n * @ingroup lavu_crypto\n * @{\n */\n\nextern const int av_tea_size;\n\nstruct AVTEA;\n\n/**\n  * Allocate an AVTEA context\n  * To free the struct: av_free(ptr)\n  */\nstruct AVTEA *av_tea_alloc(void);\n\n/**\n * Initialize an AVTEA context.\n *\n * @param ctx an AVTEA context\n * @param key a key of 16 bytes used for encryption/decryption\n * @param rounds the number of rounds in TEA (64 is the \"standard\")\n */\nvoid av_tea_init(struct AVTEA *ctx, const uint8_t key[16], int rounds);\n\n/**\n * Encrypt or decrypt a buffer using a previously initialized context.\n *\n * @param ctx an AVTEA context\n * @param dst destination array, can be equal to src\n * @param src source array, can be equal to dst\n * @param count number of 8 byte blocks\n * @param iv initialization vector for CBC mode, if NULL then ECB will be used\n * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_tea_crypt(struct AVTEA *ctx, uint8_t *dst, const uint8_t *src,\n                  int count, uint8_t *iv, int decrypt);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_TEA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/threadmessage.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public License\n * as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,\n * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_THREADMESSAGE_H\n#define AVUTIL_THREADMESSAGE_H\n\ntypedef struct AVThreadMessageQueue AVThreadMessageQueue;\n\ntypedef enum AVThreadMessageFlags {\n\n    /**\n     * Perform non-blocking operation.\n     * If this flag is set, send and recv operations are non-blocking and\n     * return AVERROR(EAGAIN) immediately if they can not proceed.\n     */\n    AV_THREAD_MESSAGE_NONBLOCK = 1,\n\n} AVThreadMessageFlags;\n\n/**\n * Allocate a new message queue.\n *\n * @param mq      pointer to the message queue\n * @param nelem   maximum number of elements in the queue\n * @param elsize  size of each element in the queue\n * @return  >=0 for success; <0 for error, in particular AVERROR(ENOSYS) if\n *          lavu was built without thread support\n */\nint av_thread_message_queue_alloc(AVThreadMessageQueue **mq,\n                                  unsigned nelem,\n                                  unsigned elsize);\n\n/**\n * Free a message queue.\n *\n * The message queue must no longer be in use by another thread.\n */\nvoid av_thread_message_queue_free(AVThreadMessageQueue **mq);\n\n/**\n * Send a message on the queue.\n */\nint av_thread_message_queue_send(AVThreadMessageQueue *mq,\n                                 void *msg,\n                                 unsigned flags);\n\n/**\n * Receive a message from the queue.\n */\nint av_thread_message_queue_recv(AVThreadMessageQueue *mq,\n                                 void *msg,\n                                 unsigned flags);\n\n/**\n * Set the sending error code.\n *\n * If the error code is set to non-zero, av_thread_message_queue_send() will\n * return it immediately. Conventional values, such as AVERROR_EOF or\n * AVERROR(EAGAIN), can be used to cause the sending thread to stop or\n * suspend its operation.\n */\nvoid av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq,\n                                          int err);\n\n/**\n * Set the receiving error code.\n *\n * If the error code is set to non-zero, av_thread_message_queue_recv() will\n * return it immediately when there are no longer available messages.\n * Conventional values, such as AVERROR_EOF or AVERROR(EAGAIN), can be used\n * to cause the receiving thread to stop or suspend its operation.\n */\nvoid av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq,\n                                          int err);\n\n/**\n * Set the optional free message callback function which will be called if an\n * operation is removing messages from the queue.\n */\nvoid av_thread_message_queue_set_free_func(AVThreadMessageQueue *mq,\n                                           void (*free_func)(void *msg));\n\n/**\n * Return the current number of messages in the queue.\n *\n * @return the current number of messages or AVERROR(ENOSYS) if lavu was built\n *         without thread support\n */\nint av_thread_message_queue_nb_elems(AVThreadMessageQueue *mq);\n\n/**\n * Flush the message queue\n *\n * This function is mostly equivalent to reading and free-ing every message\n * except that it will be done in a single operation (no lock/unlock between\n * reads).\n */\nvoid av_thread_message_flush(AVThreadMessageQueue *mq);\n\n#endif /* AVUTIL_THREADMESSAGE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/time.h",
    "content": "/*\n * Copyright (c) 2000-2003 Fabrice Bellard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_TIME_H\n#define AVUTIL_TIME_H\n\n#include <stdint.h>\n\n/**\n * Get the current time in microseconds.\n */\nint64_t av_gettime(void);\n\n/**\n * Get the current time in microseconds since some unspecified starting point.\n * On platforms that support it, the time comes from a monotonic clock\n * This property makes this time source ideal for measuring relative time.\n * The returned values may not be monotonic on platforms where a monotonic\n * clock is not available.\n */\nint64_t av_gettime_relative(void);\n\n/**\n * Indicates with a boolean result if the av_gettime_relative() time source\n * is monotonic.\n */\nint av_gettime_relative_is_monotonic(void);\n\n/**\n * Sleep for a period of time.  Although the duration is expressed in\n * microseconds, the actual delay may be rounded to the precision of the\n * system timer.\n *\n * @param  usec Number of microseconds to sleep.\n * @return zero on success or (negative) error code.\n */\nint av_usleep(unsigned usec);\n\n#endif /* AVUTIL_TIME_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/timecode.h",
    "content": "/*\n * Copyright (c) 2006 Smartjog S.A.S, Baptiste Coudurier <baptiste.coudurier@gmail.com>\n * Copyright (c) 2011-2012 Smartjog S.A.S, Clément Bœsch <clement.boesch@smartjog.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * Timecode helpers header\n */\n\n#ifndef AVUTIL_TIMECODE_H\n#define AVUTIL_TIMECODE_H\n\n#include <stdint.h>\n#include \"rational.h\"\n\n#define AV_TIMECODE_STR_SIZE 23\n\nenum AVTimecodeFlag {\n    AV_TIMECODE_FLAG_DROPFRAME      = 1<<0, ///< timecode is drop frame\n    AV_TIMECODE_FLAG_24HOURSMAX     = 1<<1, ///< timecode wraps after 24 hours\n    AV_TIMECODE_FLAG_ALLOWNEGATIVE  = 1<<2, ///< negative time values are allowed\n};\n\ntypedef struct {\n    int start;          ///< timecode frame start (first base frame number)\n    uint32_t flags;     ///< flags such as drop frame, +24 hours support, ...\n    AVRational rate;    ///< frame rate in rational form\n    unsigned fps;       ///< frame per second; must be consistent with the rate field\n} AVTimecode;\n\n/**\n * Adjust frame number for NTSC drop frame time code.\n *\n * @param framenum frame number to adjust\n * @param fps      frame per second, multiples of 30\n * @return         adjusted frame number\n * @warning        adjustment is only valid for multiples of NTSC 29.97\n */\nint av_timecode_adjust_ntsc_framenum2(int framenum, int fps);\n\n/**\n * Convert frame number to SMPTE 12M binary representation.\n *\n * @param tc       timecode data correctly initialized\n * @param framenum frame number\n * @return         the SMPTE binary representation\n *\n * See SMPTE ST 314M-2005 Sec 4.4.2.2.1 \"Time code pack (TC)\"\n * the format description as follows:\n * bits 0-5:   hours, in BCD(6bits)\n * bits 6:     BGF1\n * bits 7:     BGF2 (NTSC) or FIELD (PAL)\n * bits 8-14:  minutes, in BCD(7bits)\n * bits 15:    BGF0 (NTSC) or BGF2 (PAL)\n * bits 16-22: seconds, in BCD(7bits)\n * bits 23:    FIELD (NTSC) or BGF0 (PAL)\n * bits 24-29: frames, in BCD(6bits)\n * bits 30:    drop  frame flag (0: non drop,    1: drop)\n * bits 31:    color frame flag (0: unsync mode, 1: sync mode)\n * @note BCD numbers (6 or 7 bits): 4 or 5 lower bits for units, 2 higher bits for tens.\n * @note Frame number adjustment is automatically done in case of drop timecode,\n *       you do NOT have to call av_timecode_adjust_ntsc_framenum2().\n * @note The frame number is relative to tc->start.\n * @note Color frame (CF) and binary group flags (BGF) bits are set to zero.\n */\nuint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum);\n\n/**\n * Convert sei info to SMPTE 12M binary representation.\n *\n * @param rate     frame rate in rational form\n * @param drop     drop flag\n * @param hh       hour\n * @param mm       minute\n * @param ss       second\n * @param ff       frame number\n * @return         the SMPTE binary representation\n */\nuint32_t av_timecode_get_smpte(AVRational rate, int drop, int hh, int mm, int ss, int ff);\n\n/**\n * Load timecode string in buf.\n *\n * @param buf      destination buffer, must be at least AV_TIMECODE_STR_SIZE long\n * @param tc       timecode data correctly initialized\n * @param framenum frame number\n * @return         the buf parameter\n *\n * @note Timecode representation can be a negative timecode and have more than\n *       24 hours, but will only be honored if the flags are correctly set.\n * @note The frame number is relative to tc->start.\n */\nchar *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum);\n\n/**\n * Get the timecode string from the SMPTE timecode format.\n *\n * In contrast to av_timecode_make_smpte_tc_string this function supports 50/60\n * fps timecodes by using the field bit.\n *\n * @param buf        destination buffer, must be at least AV_TIMECODE_STR_SIZE long\n * @param rate       frame rate of the timecode\n * @param tcsmpte    the 32-bit SMPTE timecode\n * @param prevent_df prevent the use of a drop flag when it is known the DF bit\n *                   is arbitrary\n * @param skip_field prevent the use of a field flag when it is known the field\n *                   bit is arbitrary (e.g. because it is used as PC flag)\n * @return           the buf parameter\n */\nchar *av_timecode_make_smpte_tc_string2(char *buf, AVRational rate, uint32_t tcsmpte, int prevent_df, int skip_field);\n\n/**\n * Get the timecode string from the SMPTE timecode format.\n *\n * @param buf        destination buffer, must be at least AV_TIMECODE_STR_SIZE long\n * @param tcsmpte    the 32-bit SMPTE timecode\n * @param prevent_df prevent the use of a drop flag when it is known the DF bit\n *                   is arbitrary\n * @return           the buf parameter\n */\nchar *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df);\n\n/**\n * Get the timecode string from the 25-bit timecode format (MPEG GOP format).\n *\n * @param buf     destination buffer, must be at least AV_TIMECODE_STR_SIZE long\n * @param tc25bit the 25-bits timecode\n * @return        the buf parameter\n */\nchar *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit);\n\n/**\n * Init a timecode struct with the passed parameters.\n *\n * @param log_ctx     a pointer to an arbitrary struct of which the first field\n *                    is a pointer to an AVClass struct (used for av_log)\n * @param tc          pointer to an allocated AVTimecode\n * @param rate        frame rate in rational form\n * @param flags       miscellaneous flags such as drop frame, +24 hours, ...\n *                    (see AVTimecodeFlag)\n * @param frame_start the first frame number\n * @return            0 on success, AVERROR otherwise\n */\nint av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx);\n\n/**\n * Init a timecode struct from the passed timecode components.\n *\n * @param log_ctx     a pointer to an arbitrary struct of which the first field\n *                    is a pointer to an AVClass struct (used for av_log)\n * @param tc          pointer to an allocated AVTimecode\n * @param rate        frame rate in rational form\n * @param flags       miscellaneous flags such as drop frame, +24 hours, ...\n *                    (see AVTimecodeFlag)\n * @param hh          hours\n * @param mm          minutes\n * @param ss          seconds\n * @param ff          frames\n * @return            0 on success, AVERROR otherwise\n */\nint av_timecode_init_from_components(AVTimecode *tc, AVRational rate, int flags, int hh, int mm, int ss, int ff, void *log_ctx);\n\n/**\n * Parse timecode representation (hh:mm:ss[:;.]ff).\n *\n * @param log_ctx a pointer to an arbitrary struct of which the first field is a\n *                pointer to an AVClass struct (used for av_log).\n * @param tc      pointer to an allocated AVTimecode\n * @param rate    frame rate in rational form\n * @param str     timecode string which will determine the frame start\n * @return        0 on success, AVERROR otherwise\n */\nint av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx);\n\n/**\n * Check if the timecode feature is available for the given frame rate\n *\n * @return 0 if supported, <0 otherwise\n */\nint av_timecode_check_frame_rate(AVRational rate);\n\n#endif /* AVUTIL_TIMECODE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/timestamp.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * timestamp utils, mostly useful for debugging/logging purposes\n */\n\n#ifndef AVUTIL_TIMESTAMP_H\n#define AVUTIL_TIMESTAMP_H\n\n#include \"common.h\"\n\n#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS) && !defined(PRId64)\n#error missing -D__STDC_FORMAT_MACROS / #define __STDC_FORMAT_MACROS\n#endif\n\n#define AV_TS_MAX_STRING_SIZE 32\n\n/**\n * Fill the provided buffer with a string containing a timestamp\n * representation.\n *\n * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE\n * @param ts the timestamp to represent\n * @return the buffer in input\n */\nstatic inline char *av_ts_make_string(char *buf, int64_t ts)\n{\n    if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, \"NOPTS\");\n    else                      snprintf(buf, AV_TS_MAX_STRING_SIZE, \"%\" PRId64, ts);\n    return buf;\n}\n\n/**\n * Convenience macro, the return value should be used only directly in\n * function arguments but never stand-alone.\n */\n#define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts)\n\n/**\n * Fill the provided buffer with a string containing a timestamp time\n * representation.\n *\n * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE\n * @param ts the timestamp to represent\n * @param tb the timebase of the timestamp\n * @return the buffer in input\n */\nstatic inline char *av_ts_make_time_string(char *buf, int64_t ts, AVRational *tb)\n{\n    if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, \"NOPTS\");\n    else                      snprintf(buf, AV_TS_MAX_STRING_SIZE, \"%.6g\", av_q2d(*tb) * ts);\n    return buf;\n}\n\n/**\n * Convenience macro, the return value should be used only directly in\n * function arguments but never stand-alone.\n */\n#define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb)\n\n#endif /* AVUTIL_TIMESTAMP_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/tree.h",
    "content": "/*\n * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * A tree container.\n * @author Michael Niedermayer <michaelni@gmx.at>\n */\n\n#ifndef AVUTIL_TREE_H\n#define AVUTIL_TREE_H\n\n#include \"attributes.h\"\n\n/**\n * @addtogroup lavu_tree AVTree\n * @ingroup lavu_data\n *\n * Low-complexity tree container\n *\n * Insertion, removal, finding equal, largest which is smaller than and\n * smallest which is larger than, all have O(log n) worst-case complexity.\n * @{\n */\n\n\nstruct AVTreeNode;\nextern const int av_tree_node_size;\n\n/**\n * Allocate an AVTreeNode.\n */\nstruct AVTreeNode *av_tree_node_alloc(void);\n\n/**\n * Find an element.\n * @param root a pointer to the root node of the tree\n * @param next If next is not NULL, then next[0] will contain the previous\n *             element and next[1] the next element. If either does not exist,\n *             then the corresponding entry in next is unchanged.\n * @param cmp compare function used to compare elements in the tree,\n *            API identical to that of Standard C's qsort\n *            It is guaranteed that the first and only the first argument to cmp()\n *            will be the key parameter to av_tree_find(), thus it could if the\n *            user wants, be a different type (like an opaque context).\n * @return An element with cmp(key, elem) == 0 or NULL if no such element\n *         exists in the tree.\n */\nvoid *av_tree_find(const struct AVTreeNode *root, void *key,\n                   int (*cmp)(const void *key, const void *b), void *next[2]);\n\n/**\n * Insert or remove an element.\n *\n * If *next is NULL, then the supplied element will be removed if it exists.\n * If *next is non-NULL, then the supplied element will be inserted, unless\n * it already exists in the tree.\n *\n * @param rootp A pointer to a pointer to the root node of the tree; note that\n *              the root node can change during insertions, this is required\n *              to keep the tree balanced.\n * @param key  pointer to the element key to insert in the tree\n * @param next Used to allocate and free AVTreeNodes. For insertion the user\n *             must set it to an allocated and zeroed object of at least\n *             av_tree_node_size bytes size. av_tree_insert() will set it to\n *             NULL if it has been consumed.\n *             For deleting elements *next is set to NULL by the user and\n *             av_tree_insert() will set it to the AVTreeNode which was\n *             used for the removed element.\n *             This allows the use of flat arrays, which have\n *             lower overhead compared to many malloced elements.\n *             You might want to define a function like:\n *             @code\n *             void *tree_insert(struct AVTreeNode **rootp, void *key,\n *                               int (*cmp)(void *key, const void *b),\n *                               AVTreeNode **next)\n *             {\n *                 if (!*next)\n *                     *next = av_mallocz(av_tree_node_size);\n *                 return av_tree_insert(rootp, key, cmp, next);\n *             }\n *             void *tree_remove(struct AVTreeNode **rootp, void *key,\n *                               int (*cmp)(void *key, const void *b, AVTreeNode **next))\n *             {\n *                 av_freep(next);\n *                 return av_tree_insert(rootp, key, cmp, next);\n *             }\n *             @endcode\n * @param cmp compare function used to compare elements in the tree, API identical\n *            to that of Standard C's qsort\n * @return If no insertion happened, the found element; if an insertion or\n *         removal happened, then either key or NULL will be returned.\n *         Which one it is depends on the tree state and the implementation. You\n *         should make no assumptions that it's one or the other in the code.\n */\nvoid *av_tree_insert(struct AVTreeNode **rootp, void *key,\n                     int (*cmp)(const void *key, const void *b),\n                     struct AVTreeNode **next);\n\nvoid av_tree_destroy(struct AVTreeNode *t);\n\n/**\n * Apply enu(opaque, &elem) to all the elements in the tree in a given range.\n *\n * @param cmp a comparison function that returns < 0 for an element below the\n *            range, > 0 for an element above the range and == 0 for an\n *            element inside the range\n *\n * @note The cmp function should use the same ordering used to construct the\n *       tree.\n */\nvoid av_tree_enumerate(struct AVTreeNode *t, void *opaque,\n                       int (*cmp)(void *opaque, void *elem),\n                       int (*enu)(void *opaque, void *elem));\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_TREE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/twofish.h",
    "content": "/*\n * An implementation of the TwoFish algorithm\n * Copyright (c) 2015 Supraja Meedinti\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_TWOFISH_H\n#define AVUTIL_TWOFISH_H\n\n#include <stdint.h>\n\n\n/**\n  * @file\n  * @brief Public header for libavutil TWOFISH algorithm\n  * @defgroup lavu_twofish TWOFISH\n  * @ingroup lavu_crypto\n  * @{\n  */\n\nextern const int av_twofish_size;\n\nstruct AVTWOFISH;\n\n/**\n  * Allocate an AVTWOFISH context\n  * To free the struct: av_free(ptr)\n  */\nstruct AVTWOFISH *av_twofish_alloc(void);\n\n/**\n  * Initialize an AVTWOFISH context.\n  *\n  * @param ctx an AVTWOFISH context\n  * @param key a key of size ranging from 1 to 32 bytes used for encryption/decryption\n  * @param key_bits number of keybits: 128, 192, 256 If less than the required, padded with zeroes to nearest valid value; return value is 0 if key_bits is 128/192/256, -1 if less than 0, 1 otherwise\n */\nint av_twofish_init(struct AVTWOFISH *ctx, const uint8_t *key, int key_bits);\n\n/**\n  * Encrypt or decrypt a buffer using a previously initialized context\n  *\n  * @param ctx an AVTWOFISH context\n  * @param dst destination array, can be equal to src\n  * @param src source array, can be equal to dst\n  * @param count number of 16 byte blocks\n  * @paran iv initialization vector for CBC mode, NULL for ECB mode\n  * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_twofish_crypt(struct AVTWOFISH *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t* iv, int decrypt);\n\n/**\n * @}\n */\n#endif /* AVUTIL_TWOFISH_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/tx.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_TX_H\n#define AVUTIL_TX_H\n\n#include <stdint.h>\n#include <stddef.h>\n\ntypedef struct AVTXContext AVTXContext;\n\ntypedef struct AVComplexFloat {\n    float re, im;\n} AVComplexFloat;\n\ntypedef struct AVComplexDouble {\n    double re, im;\n} AVComplexDouble;\n\ntypedef struct AVComplexInt32 {\n    int32_t re, im;\n} AVComplexInt32;\n\nenum AVTXType {\n    /**\n     * Standard complex to complex FFT with sample data type of AVComplexFloat,\n     * AVComplexDouble or AVComplexInt32, for each respective variant.\n     *\n     * Output is not 1/len normalized. Scaling currently unsupported.\n     * The stride parameter must be set to the size of a single sample in bytes.\n     */\n    AV_TX_FLOAT_FFT  = 0,\n    AV_TX_DOUBLE_FFT = 2,\n    AV_TX_INT32_FFT  = 4,\n\n    /**\n     * Standard MDCT with a sample data type of float, double or int32_t,\n     * respecively. For the float and int32 variants, the scale type is\n     * 'float', while for the double variant, it's 'double'.\n     * If scale is NULL, 1.0 will be used as a default.\n     *\n     * Length is the frame size, not the window size (which is 2x frame).\n     * For forward transforms, the stride specifies the spacing between each\n     * sample in the output array in bytes. The input must be a flat array.\n     *\n     * For inverse transforms, the stride specifies the spacing between each\n     * sample in the input array in bytes. The output must be a flat array.\n     *\n     * NOTE: the inverse transform is half-length, meaning the output will not\n     * contain redundant data. This is what most codecs work with. To do a full\n     * inverse transform, set the AV_TX_FULL_IMDCT flag on init.\n     */\n    AV_TX_FLOAT_MDCT  = 1,\n    AV_TX_DOUBLE_MDCT = 3,\n    AV_TX_INT32_MDCT  = 5,\n\n    /**\n     * Real to complex and complex to real DFTs.\n     * For the float and int32 variants, the scale type is 'float', while for\n     * the double variant, it's a 'double'. If scale is NULL, 1.0 will be used\n     * as a default.\n     *\n     * The stride parameter must be set to the size of a single sample in bytes.\n     *\n     * The forward transform performs a real-to-complex DFT of N samples to\n     * N/2+1 complex values.\n     *\n     * The inverse transform performs a complex-to-real DFT of N/2+1 complex\n     * values to N real samples. The output is not normalized, but can be\n     * made so by setting the scale value to 1.0/len.\n     * NOTE: the inverse transform always overwrites the input.\n     */\n    AV_TX_FLOAT_RDFT  = 6,\n    AV_TX_DOUBLE_RDFT = 7,\n    AV_TX_INT32_RDFT  = 8,\n\n    /* Not part of the API, do not use */\n    AV_TX_NB,\n};\n\n/**\n * Function pointer to a function to perform the transform.\n *\n * @note Using a different context than the one allocated during av_tx_init()\n * is not allowed.\n *\n * @param s the transform context\n * @param out the output array\n * @param in the input array\n * @param stride the input or output stride in bytes\n *\n * The out and in arrays must be aligned to the maximum required by the CPU\n * architecture unless the AV_TX_UNALIGNED flag was set in av_tx_init().\n * The stride must follow the constraints the transform type has specified.\n */\ntypedef void (*av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride);\n\n/**\n * Flags for av_tx_init()\n */\nenum AVTXFlags {\n    /**\n     * Performs an in-place transformation on the input. The output argument\n     * of av_tn_fn() MUST match the input. May be unsupported or slower for some\n     * transform types.\n     */\n    AV_TX_INPLACE = 1ULL << 0,\n\n    /**\n     * Relaxes alignment requirement for the in and out arrays of av_tx_fn().\n     * May be slower with certain transform types.\n     */\n    AV_TX_UNALIGNED = 1ULL << 1,\n\n    /**\n     * Performs a full inverse MDCT rather than leaving out samples that can be\n     * derived through symmetry. Requires an output array of 'len' floats,\n     * rather than the usual 'len/2' floats.\n     * Ignored for all transforms but inverse MDCTs.\n     */\n    AV_TX_FULL_IMDCT = 1ULL << 2,\n};\n\n/**\n * Initialize a transform context with the given configuration\n * (i)MDCTs with an odd length are currently not supported.\n *\n * @param ctx the context to allocate, will be NULL on error\n * @param tx pointer to the transform function pointer to set\n * @param type type the type of transform\n * @param inv whether to do an inverse or a forward transform\n * @param len the size of the transform in samples\n * @param scale pointer to the value to scale the output if supported by type\n * @param flags a bitmask of AVTXFlags or 0\n *\n * @return 0 on success, negative error code on failure\n */\nint av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type,\n               int inv, int len, const void *scale, uint64_t flags);\n\n/**\n * Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.\n */\nvoid av_tx_uninit(AVTXContext **ctx);\n\n#endif /* AVUTIL_TX_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/uuid.h",
    "content": "/*\n * Copyright (c) 2022 Pierre-Anthony Lemieux <pal@palemieux.com>\n *                    Zane van Iperen <zane@zanevaniperen.com>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * UUID parsing and serialization utilities.\n * The library treats the UUID as an opaque sequence of 16 unsigned bytes,\n * i.e. ignoring the internal layout of the UUID, which depends on the type\n * of the UUID.\n *\n * @author Pierre-Anthony Lemieux <pal@palemieux.com>\n * @author Zane van Iperen <zane@zanevaniperen.com>\n */\n\n#ifndef AVUTIL_UUID_H\n#define AVUTIL_UUID_H\n\n#include <stdint.h>\n#include <string.h>\n\n#define AV_PRI_UUID                          \\\n    \"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-\" \\\n    \"%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\"\n\n#define AV_PRI_URN_UUID                               \\\n    \"urn:uuid:%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-\" \\\n    \"%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\"\n\n/* AV_UUID_ARG() is used together with AV_PRI_UUID() or AV_PRI_URN_UUID\n * to print UUIDs, e.g.\n * av_log(NULL, AV_LOG_DEBUG, \"UUID: \" AV_PRI_UUID, AV_UUID_ARG(uuid));\n */\n#define AV_UUID_ARG(x)                  \\\n    (x)[ 0], (x)[ 1], (x)[ 2], (x)[ 3], \\\n    (x)[ 4], (x)[ 5], (x)[ 6], (x)[ 7], \\\n    (x)[ 8], (x)[ 9], (x)[10], (x)[11], \\\n    (x)[12], (x)[13], (x)[14], (x)[15]\n\n#define AV_UUID_LEN 16\n\n/* Binary representation of a UUID */\ntypedef uint8_t AVUUID[AV_UUID_LEN];\n\n/**\n * Parses a string representation of a UUID formatted according to IETF RFC 4122\n * into an AVUUID. The parsing is case-insensitive. The string must be 37\n * characters long, including the terminating NUL character.\n *\n * Example string representation: \"2fceebd0-7017-433d-bafb-d073a7116696\"\n *\n * @param[in]  in  String representation of a UUID,\n *                 e.g. 2fceebd0-7017-433d-bafb-d073a7116696\n * @param[out] uu  AVUUID\n * @return         A non-zero value in case of an error.\n */\nint av_uuid_parse(const char *in, AVUUID uu);\n\n/**\n * Parses a URN representation of a UUID, as specified at IETF RFC 4122,\n * into an AVUUID. The parsing is case-insensitive. The string must be 46\n * characters long, including the terminating NUL character.\n *\n * Example string representation: \"urn:uuid:2fceebd0-7017-433d-bafb-d073a7116696\"\n *\n * @param[in]  in  URN UUID\n * @param[out] uu  AVUUID\n * @return         A non-zero value in case of an error.\n */\nint av_uuid_urn_parse(const char *in, AVUUID uu);\n\n/**\n * Parses a string representation of a UUID formatted according to IETF RFC 4122\n * into an AVUUID. The parsing is case-insensitive.\n *\n * @param[in]  in_start Pointer to the first character of the string representation\n * @param[in]  in_end   Pointer to the character after the last character of the\n *                      string representation. That memory location is never\n *                      accessed. It is an error if `in_end - in_start != 36`.\n * @param[out] uu       AVUUID\n * @return              A non-zero value in case of an error.\n */\nint av_uuid_parse_range(const char *in_start, const char *in_end, AVUUID uu);\n\n/**\n * Serializes a AVUUID into a string representation according to IETF RFC 4122.\n * The string is lowercase and always 37 characters long, including the\n * terminating NUL character.\n *\n * @param[in]  uu  AVUUID\n * @param[out] out Pointer to an array of no less than 37 characters.\n * @return         A non-zero value in case of an error.\n */\nvoid av_uuid_unparse(const AVUUID uu, char *out);\n\n/**\n * Compares two UUIDs for equality.\n *\n * @param[in]  uu1  AVUUID\n * @param[in]  uu2  AVUUID\n * @return          Nonzero if uu1 and uu2 are identical, 0 otherwise\n */\nstatic inline int av_uuid_equal(const AVUUID uu1, const AVUUID uu2)\n{\n    return memcmp(uu1, uu2, AV_UUID_LEN) == 0;\n}\n\n/**\n * Copies the bytes of src into dest.\n *\n * @param[out]  dest  AVUUID\n * @param[in]   src   AVUUID\n */\nstatic inline void av_uuid_copy(AVUUID dest, const AVUUID src)\n{\n    memcpy(dest, src, AV_UUID_LEN);\n}\n\n/**\n * Sets a UUID to the nil UUID, i.e. a UUID with have all\n * its 128 bits set to zero.\n *\n * @param[in,out]  uu  UUID to be set to the nil UUID\n */\nstatic inline void av_uuid_nil(AVUUID uu)\n{\n    memset(uu, 0, AV_UUID_LEN);\n}\n\n#endif /* AVUTIL_UUID_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/version.h",
    "content": "/*\n * copyright (c) 2003 Fabrice Bellard\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n/**\n * @file\n * @ingroup lavu\n * Libavutil version macros\n */\n\n#ifndef AVUTIL_VERSION_H\n#define AVUTIL_VERSION_H\n\n#include \"macros.h\"\n\n/**\n * @addtogroup version_utils\n *\n * Useful to check and match library version in order to maintain\n * backward compatibility.\n *\n * The FFmpeg libraries follow a versioning sheme very similar to\n * Semantic Versioning (http://semver.org/)\n * The difference is that the component called PATCH is called MICRO in FFmpeg\n * and its value is reset to 100 instead of 0 to keep it above or equal to 100.\n * Also we do not increase MICRO for every bugfix or change in git master.\n *\n * Prior to FFmpeg 3.2 point releases did not change any lib version number to\n * avoid aliassing different git master checkouts.\n * Starting with FFmpeg 3.2, the released library versions will occupy\n * a separate MAJOR.MINOR that is not used on the master development branch.\n * That is if we branch a release of master 55.10.123 we will bump to 55.11.100\n * for the release and master will continue at 55.12.100 after it. Each new\n * point release will then bump the MICRO improving the usefulness of the lib\n * versions.\n *\n * @{\n */\n\n#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c))\n#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c\n#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c)\n\n/**\n * Extract version components from the full ::AV_VERSION_INT int as returned\n * by functions like ::avformat_version() and ::avcodec_version()\n */\n#define AV_VERSION_MAJOR(a) ((a) >> 16)\n#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8)\n#define AV_VERSION_MICRO(a) ((a) & 0xFF)\n\n/**\n * @}\n */\n\n/**\n * @defgroup lavu_ver Version and Build diagnostics\n *\n * Macros and function useful to check at compiletime and at runtime\n * which version of libavutil is in use.\n *\n * @{\n */\n\n#define LIBAVUTIL_VERSION_MAJOR  57\n#define LIBAVUTIL_VERSION_MINOR  28\n#define LIBAVUTIL_VERSION_MICRO 100\n\n#define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \\\n                                               LIBAVUTIL_VERSION_MINOR, \\\n                                               LIBAVUTIL_VERSION_MICRO)\n#define LIBAVUTIL_VERSION       AV_VERSION(LIBAVUTIL_VERSION_MAJOR,     \\\n                                           LIBAVUTIL_VERSION_MINOR,     \\\n                                           LIBAVUTIL_VERSION_MICRO)\n#define LIBAVUTIL_BUILD         LIBAVUTIL_VERSION_INT\n\n#define LIBAVUTIL_IDENT         \"Lavu\" AV_STRINGIFY(LIBAVUTIL_VERSION)\n\n/**\n * @defgroup lavu_depr_guards Deprecation Guards\n * FF_API_* defines may be placed below to indicate public API that will be\n * dropped at a future version bump. The defines themselves are not part of\n * the public API and may change, break or disappear at any time.\n *\n * @note, when bumping the major version it is recommended to manually\n * disable each FF_API_* in its own commit instead of disabling them all\n * at once through the bump. This improves the git bisect-ability of the change.\n *\n * @{\n */\n\n#define FF_API_D2STR                    (LIBAVUTIL_VERSION_MAJOR < 58)\n#define FF_API_DECLARE_ALIGNED          (LIBAVUTIL_VERSION_MAJOR < 58)\n#define FF_API_COLORSPACE_NAME          (LIBAVUTIL_VERSION_MAJOR < 58)\n#define FF_API_AV_MALLOCZ_ARRAY         (LIBAVUTIL_VERSION_MAJOR < 58)\n#define FF_API_FIFO_PEEK2               (LIBAVUTIL_VERSION_MAJOR < 58)\n#define FF_API_FIFO_OLD_API             (LIBAVUTIL_VERSION_MAJOR < 58)\n#define FF_API_XVMC                     (LIBAVUTIL_VERSION_MAJOR < 58)\n#define FF_API_OLD_CHANNEL_LAYOUT       (LIBAVUTIL_VERSION_MAJOR < 58)\n#define FF_API_AV_FOPEN_UTF8            (LIBAVUTIL_VERSION_MAJOR < 58)\n\n/**\n * @}\n * @}\n */\n\n#endif /* AVUTIL_VERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/video_enc_params.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_VIDEO_ENC_PARAMS_H\n#define AVUTIL_VIDEO_ENC_PARAMS_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"libavutil/avassert.h\"\n#include \"libavutil/frame.h\"\n\nenum AVVideoEncParamsType {\n    AV_VIDEO_ENC_PARAMS_NONE = -1,\n    /**\n     * VP9 stores:\n     * - per-frame base (luma AC) quantizer index, exported as AVVideoEncParams.qp\n     * - deltas for luma DC, chroma AC and chroma DC, exported in the\n     *   corresponding entries in AVVideoEncParams.delta_qp\n     * - per-segment delta, exported as for each block as AVVideoBlockParams.delta_qp\n     *\n     * To compute the resulting quantizer index for a block:\n     * - for luma AC, add the base qp and the per-block delta_qp, saturating to\n     *   unsigned 8-bit.\n     * - for luma DC and chroma AC/DC, add the corresponding\n     *   AVVideoBlockParams.delta_qp to the luma AC index, again saturating to\n     *   unsigned 8-bit.\n     */\n    AV_VIDEO_ENC_PARAMS_VP9,\n\n    /**\n     * H.264 stores:\n     * - in PPS (per-picture):\n     *   * initial QP_Y (luma) value, exported as AVVideoEncParams.qp\n     *   * delta(s) for chroma QP values (same for both, or each separately),\n     *     exported as in the corresponding entries in AVVideoEncParams.delta_qp\n     * - per-slice QP delta, not exported directly, added to the per-MB value\n     * - per-MB delta; not exported directly; the final per-MB quantizer\n     *   parameter - QP_Y - minus the value in AVVideoEncParams.qp is exported\n     *   as AVVideoBlockParams.qp_delta.\n     */\n    AV_VIDEO_ENC_PARAMS_H264,\n\n    /*\n     * MPEG-2-compatible quantizer.\n     *\n     * Summing the frame-level qp with the per-block delta_qp gives the\n     * resulting quantizer for the block.\n     */\n    AV_VIDEO_ENC_PARAMS_MPEG2,\n};\n\n/**\n * Video encoding parameters for a given frame. This struct is allocated along\n * with an optional array of per-block AVVideoBlockParams descriptors.\n * Must be allocated with av_video_enc_params_alloc().\n */\ntypedef struct AVVideoEncParams {\n    /**\n     * Number of blocks in the array.\n     *\n     * May be 0, in which case no per-block information is present. In this case\n     * the values of blocks_offset / block_size are unspecified and should not\n     * be accessed.\n     */\n    unsigned int nb_blocks;\n    /**\n     * Offset in bytes from the beginning of this structure at which the array\n     * of blocks starts.\n     */\n    size_t blocks_offset;\n    /*\n     * Size of each block in bytes. May not match sizeof(AVVideoBlockParams).\n     */\n    size_t block_size;\n\n    /**\n     * Type of the parameters (the codec they are used with).\n     */\n    enum AVVideoEncParamsType type;\n\n    /**\n     * Base quantisation parameter for the frame. The final quantiser for a\n     * given block in a given plane is obtained from this value, possibly\n     * combined with {@code delta_qp} and the per-block delta in a manner\n     * documented for each type.\n     */\n    int32_t qp;\n\n    /**\n     * Quantisation parameter offset from the base (per-frame) qp for a given\n     * plane (first index) and AC/DC coefficients (second index).\n     */\n    int32_t delta_qp[4][2];\n} AVVideoEncParams;\n\n/**\n * Data structure for storing block-level encoding information.\n * It is allocated as a part of AVVideoEncParams and should be retrieved with\n * av_video_enc_params_block().\n *\n * sizeof(AVVideoBlockParams) is not a part of the ABI and new fields may be\n * added to it.\n */\ntypedef struct AVVideoBlockParams {\n    /**\n     * Distance in luma pixels from the top-left corner of the visible frame\n     * to the top-left corner of the block.\n     * Can be negative if top/right padding is present on the coded frame.\n     */\n    int src_x, src_y;\n    /**\n     * Width and height of the block in luma pixels.\n     */\n    int w, h;\n\n    /**\n     * Difference between this block's final quantization parameter and the\n     * corresponding per-frame value.\n     */\n    int32_t delta_qp;\n} AVVideoBlockParams;\n\n/*\n * Get the block at the specified {@code idx}. Must be between 0 and nb_blocks.\n */\nstatic av_always_inline AVVideoBlockParams*\nav_video_enc_params_block(AVVideoEncParams *par, unsigned int idx)\n{\n    av_assert0(idx < par->nb_blocks);\n    return (AVVideoBlockParams *)((uint8_t *)par + par->blocks_offset +\n                                  idx * par->block_size);\n}\n\n/**\n * Allocates memory for AVVideoEncParams of the given type, plus an array of\n * {@code nb_blocks} AVVideoBlockParams and initializes the variables. Can be\n * freed with a normal av_free() call.\n *\n * @param out_size if non-NULL, the size in bytes of the resulting data array is\n * written here.\n */\nAVVideoEncParams *av_video_enc_params_alloc(enum AVVideoEncParamsType type,\n                                            unsigned int nb_blocks, size_t *out_size);\n\n/**\n * Allocates memory for AVEncodeInfoFrame plus an array of\n * {@code nb_blocks} AVEncodeInfoBlock in the given AVFrame {@code frame}\n * as AVFrameSideData of type AV_FRAME_DATA_VIDEO_ENC_PARAMS\n * and initializes the variables.\n */\nAVVideoEncParams*\nav_video_enc_params_create_side_data(AVFrame *frame, enum AVVideoEncParamsType type,\n                                     unsigned int nb_blocks);\n\n#endif /* AVUTIL_VIDEO_ENC_PARAMS_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libavutil/xtea.h",
    "content": "/*\n * A 32-bit implementation of the XTEA algorithm\n * Copyright (c) 2012 Samuel Pitoiset\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef AVUTIL_XTEA_H\n#define AVUTIL_XTEA_H\n\n#include <stdint.h>\n\n/**\n * @file\n * @brief Public header for libavutil XTEA algorithm\n * @defgroup lavu_xtea XTEA\n * @ingroup lavu_crypto\n * @{\n */\n\ntypedef struct AVXTEA {\n    uint32_t key[16];\n} AVXTEA;\n\n/**\n * Allocate an AVXTEA context.\n */\nAVXTEA *av_xtea_alloc(void);\n\n/**\n * Initialize an AVXTEA context.\n *\n * @param ctx an AVXTEA context\n * @param key a key of 16 bytes used for encryption/decryption,\n *            interpreted as big endian 32 bit numbers\n */\nvoid av_xtea_init(struct AVXTEA *ctx, const uint8_t key[16]);\n\n/**\n * Initialize an AVXTEA context.\n *\n * @param ctx an AVXTEA context\n * @param key a key of 16 bytes used for encryption/decryption,\n *            interpreted as little endian 32 bit numbers\n */\nvoid av_xtea_le_init(struct AVXTEA *ctx, const uint8_t key[16]);\n\n/**\n * Encrypt or decrypt a buffer using a previously initialized context,\n * in big endian format.\n *\n * @param ctx an AVXTEA context\n * @param dst destination array, can be equal to src\n * @param src source array, can be equal to dst\n * @param count number of 8 byte blocks\n * @param iv initialization vector for CBC mode, if NULL then ECB will be used\n * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_xtea_crypt(struct AVXTEA *ctx, uint8_t *dst, const uint8_t *src,\n                   int count, uint8_t *iv, int decrypt);\n\n/**\n * Encrypt or decrypt a buffer using a previously initialized context,\n * in little endian format.\n *\n * @param ctx an AVXTEA context\n * @param dst destination array, can be equal to src\n * @param src source array, can be equal to dst\n * @param count number of 8 byte blocks\n * @param iv initialization vector for CBC mode, if NULL then ECB will be used\n * @param decrypt 0 for encryption, 1 for decryption\n */\nvoid av_xtea_le_crypt(struct AVXTEA *ctx, uint8_t *dst, const uint8_t *src,\n                      int count, uint8_t *iv, int decrypt);\n\n/**\n * @}\n */\n\n#endif /* AVUTIL_XTEA_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libpostproc/postprocess.h",
    "content": "/*\n * Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at)\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef POSTPROC_POSTPROCESS_H\n#define POSTPROC_POSTPROCESS_H\n\n/**\n * @file\n * @ingroup lpp\n * external API header\n */\n\n/**\n * @defgroup lpp libpostproc\n * Video postprocessing library.\n *\n * @{\n */\n\n#include \"libpostproc/version_major.h\"\n#ifndef HAVE_AV_CONFIG_H\n/* When included as part of the ffmpeg build, only include the major version\n * to avoid unnecessary rebuilds. When included externally, keep including\n * the full version information. */\n#include \"libpostproc/version.h\"\n#endif\n\n/**\n * Return the LIBPOSTPROC_VERSION_INT constant.\n */\nunsigned postproc_version(void);\n\n/**\n * Return the libpostproc build-time configuration.\n */\nconst char *postproc_configuration(void);\n\n/**\n * Return the libpostproc license.\n */\nconst char *postproc_license(void);\n\n#define PP_QUALITY_MAX 6\n\n#include <inttypes.h>\n\ntypedef void pp_context;\ntypedef void pp_mode;\n\nextern const char pp_help[]; ///< a simple help text\n\nvoid  pp_postprocess(const uint8_t * src[3], const int srcStride[3],\n                     uint8_t * dst[3], const int dstStride[3],\n                     int horizontalSize, int verticalSize,\n                     const int8_t *QP_store,  int QP_stride,\n                     pp_mode *mode, pp_context *ppContext, int pict_type);\n\n\n/**\n * Return a pp_mode or NULL if an error occurred.\n *\n * @param name    the string after \"-pp\" on the command line\n * @param quality a number from 0 to PP_QUALITY_MAX\n */\npp_mode *pp_get_mode_by_name_and_quality(const char *name, int quality);\nvoid pp_free_mode(pp_mode *mode);\n\npp_context *pp_get_context(int width, int height, int flags);\nvoid pp_free_context(pp_context *ppContext);\n\n#define PP_CPU_CAPS_MMX   0x80000000\n#define PP_CPU_CAPS_MMX2  0x20000000\n#define PP_CPU_CAPS_3DNOW 0x40000000\n#define PP_CPU_CAPS_ALTIVEC 0x10000000\n#define PP_CPU_CAPS_AUTO  0x00080000\n\n#define PP_FORMAT         0x00000008\n#define PP_FORMAT_420    (0x00000011|PP_FORMAT)\n#define PP_FORMAT_422    (0x00000001|PP_FORMAT)\n#define PP_FORMAT_411    (0x00000002|PP_FORMAT)\n#define PP_FORMAT_444    (0x00000000|PP_FORMAT)\n#define PP_FORMAT_440    (0x00000010|PP_FORMAT)\n\n#define PP_PICT_TYPE_QP2  0x00000010 ///< MPEG2 style QScale\n\n/**\n * @}\n */\n\n#endif /* POSTPROC_POSTPROCESS_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libpostproc/version.h",
    "content": "/*\n * Version macros.\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef POSTPROC_VERSION_H\n#define POSTPROC_VERSION_H\n\n/**\n * @file\n * Libpostproc version macros\n */\n\n#include \"libavutil/version.h\"\n\n#include \"version_major.h\"\n\n#define LIBPOSTPROC_VERSION_MINOR   6\n#define LIBPOSTPROC_VERSION_MICRO 100\n\n#define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \\\n                                               LIBPOSTPROC_VERSION_MINOR, \\\n                                               LIBPOSTPROC_VERSION_MICRO)\n#define LIBPOSTPROC_VERSION     AV_VERSION(LIBPOSTPROC_VERSION_MAJOR, \\\n                                           LIBPOSTPROC_VERSION_MINOR, \\\n                                           LIBPOSTPROC_VERSION_MICRO)\n#define LIBPOSTPROC_BUILD       LIBPOSTPROC_VERSION_INT\n\n#define LIBPOSTPROC_IDENT       \"postproc\" AV_STRINGIFY(LIBPOSTPROC_VERSION)\n\n#endif /* POSTPROC_VERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libpostproc/version_major.h",
    "content": "/*\n * Version macros.\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef POSTPROC_VERSION_MAJOR_H\n#define POSTPROC_VERSION_MAJOR_H\n\n/**\n * @file\n * Libpostproc version macros\n */\n\n#define LIBPOSTPROC_VERSION_MAJOR  56\n\n#endif /* POSTPROC_VERSION_MAJOR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libswresample/swresample.h",
    "content": "/*\n * Copyright (C) 2011-2013 Michael Niedermayer (michaelni@gmx.at)\n *\n * This file is part of libswresample\n *\n * libswresample is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * libswresample is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with libswresample; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef SWRESAMPLE_SWRESAMPLE_H\n#define SWRESAMPLE_SWRESAMPLE_H\n\n/**\n * @file\n * @ingroup lswr\n * libswresample public header\n */\n\n/**\n * @defgroup lswr libswresample\n * @{\n *\n * Audio resampling, sample format conversion and mixing library.\n *\n * Interaction with lswr is done through SwrContext, which is\n * allocated with swr_alloc() or swr_alloc_set_opts2(). It is opaque, so all parameters\n * must be set with the @ref avoptions API.\n *\n * The first thing you will need to do in order to use lswr is to allocate\n * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts2(). If you\n * are using the former, you must set options through the @ref avoptions API.\n * The latter function provides the same feature, but it allows you to set some\n * common options in the same statement.\n *\n * For example the following code will setup conversion from planar float sample\n * format to interleaved signed 16-bit integer, downsampling from 48kHz to\n * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing\n * matrix). This is using the swr_alloc() function.\n * @code\n * SwrContext *swr = swr_alloc();\n * av_opt_set_channel_layout(swr, \"in_channel_layout\",  AV_CH_LAYOUT_5POINT1, 0);\n * av_opt_set_channel_layout(swr, \"out_channel_layout\", AV_CH_LAYOUT_STEREO,  0);\n * av_opt_set_int(swr, \"in_sample_rate\",     48000,                0);\n * av_opt_set_int(swr, \"out_sample_rate\",    44100,                0);\n * av_opt_set_sample_fmt(swr, \"in_sample_fmt\",  AV_SAMPLE_FMT_FLTP, 0);\n * av_opt_set_sample_fmt(swr, \"out_sample_fmt\", AV_SAMPLE_FMT_S16,  0);\n * @endcode\n *\n * The same job can be done using swr_alloc_set_opts2() as well:\n * @code\n * SwrContext *swr = NULL;\n * int ret = swr_alloc_set_opts2(&swr,         // we're allocating a new context\n *                       &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, // out_ch_layout\n *                       AV_SAMPLE_FMT_S16,    // out_sample_fmt\n *                       44100,                // out_sample_rate\n *                       &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1, // in_ch_layout\n *                       AV_SAMPLE_FMT_FLTP,   // in_sample_fmt\n *                       48000,                // in_sample_rate\n *                       0,                    // log_offset\n *                       NULL);                // log_ctx\n * @endcode\n *\n * Once all values have been set, it must be initialized with swr_init(). If\n * you need to change the conversion parameters, you can change the parameters\n * using @ref AVOptions, as described above in the first example; or by using\n * swr_alloc_set_opts2(), but with the first argument the allocated context.\n * You must then call swr_init() again.\n *\n * The conversion itself is done by repeatedly calling swr_convert().\n * Note that the samples may get buffered in swr if you provide insufficient\n * output space or if sample rate conversion is done, which requires \"future\"\n * samples. Samples that do not require future input can be retrieved at any\n * time by using swr_convert() (in_count can be set to 0).\n * At the end of conversion the resampling buffer can be flushed by calling\n * swr_convert() with NULL in and 0 in_count.\n *\n * The samples used in the conversion process can be managed with the libavutil\n * @ref lavu_sampmanip \"samples manipulation\" API, including av_samples_alloc()\n * function used in the following example.\n *\n * The delay between input and output, can at any time be found by using\n * swr_get_delay().\n *\n * The following code demonstrates the conversion loop assuming the parameters\n * from above and caller-defined functions get_input() and handle_output():\n * @code\n * uint8_t **input;\n * int in_samples;\n *\n * while (get_input(&input, &in_samples)) {\n *     uint8_t *output;\n *     int out_samples = av_rescale_rnd(swr_get_delay(swr, 48000) +\n *                                      in_samples, 44100, 48000, AV_ROUND_UP);\n *     av_samples_alloc(&output, NULL, 2, out_samples,\n *                      AV_SAMPLE_FMT_S16, 0);\n *     out_samples = swr_convert(swr, &output, out_samples,\n *                                      input, in_samples);\n *     handle_output(output, out_samples);\n *     av_freep(&output);\n * }\n * @endcode\n *\n * When the conversion is finished, the conversion\n * context and everything associated with it must be freed with swr_free().\n * A swr_close() function is also available, but it exists mainly for\n * compatibility with libavresample, and is not required to be called.\n *\n * There will be no memory leak if the data is not completely flushed before\n * swr_free().\n */\n\n#include <stdint.h>\n#include \"libavutil/channel_layout.h\"\n#include \"libavutil/frame.h\"\n#include \"libavutil/samplefmt.h\"\n\n#include \"libswresample/version_major.h\"\n#ifndef HAVE_AV_CONFIG_H\n/* When included as part of the ffmpeg build, only include the major version\n * to avoid unnecessary rebuilds. When included externally, keep including\n * the full version information. */\n#include \"libswresample/version.h\"\n#endif\n\n/**\n * @name Option constants\n * These constants are used for the @ref avoptions interface for lswr.\n * @{\n *\n */\n\n#define SWR_FLAG_RESAMPLE 1 ///< Force resampling even if equal sample rate\n//TODO use int resample ?\n//long term TODO can we enable this dynamically?\n\n/** Dithering algorithms */\nenum SwrDitherType {\n    SWR_DITHER_NONE = 0,\n    SWR_DITHER_RECTANGULAR,\n    SWR_DITHER_TRIANGULAR,\n    SWR_DITHER_TRIANGULAR_HIGHPASS,\n\n    SWR_DITHER_NS = 64,         ///< not part of API/ABI\n    SWR_DITHER_NS_LIPSHITZ,\n    SWR_DITHER_NS_F_WEIGHTED,\n    SWR_DITHER_NS_MODIFIED_E_WEIGHTED,\n    SWR_DITHER_NS_IMPROVED_E_WEIGHTED,\n    SWR_DITHER_NS_SHIBATA,\n    SWR_DITHER_NS_LOW_SHIBATA,\n    SWR_DITHER_NS_HIGH_SHIBATA,\n    SWR_DITHER_NB,              ///< not part of API/ABI\n};\n\n/** Resampling Engines */\nenum SwrEngine {\n    SWR_ENGINE_SWR,             /**< SW Resampler */\n    SWR_ENGINE_SOXR,            /**< SoX Resampler */\n    SWR_ENGINE_NB,              ///< not part of API/ABI\n};\n\n/** Resampling Filter Types */\nenum SwrFilterType {\n    SWR_FILTER_TYPE_CUBIC,              /**< Cubic */\n    SWR_FILTER_TYPE_BLACKMAN_NUTTALL,   /**< Blackman Nuttall windowed sinc */\n    SWR_FILTER_TYPE_KAISER,             /**< Kaiser windowed sinc */\n};\n\n/**\n * @}\n */\n\n/**\n * The libswresample context. Unlike libavcodec and libavformat, this structure\n * is opaque. This means that if you would like to set options, you must use\n * the @ref avoptions API and cannot directly set values to members of the\n * structure.\n */\ntypedef struct SwrContext SwrContext;\n\n/**\n * Get the AVClass for SwrContext. It can be used in combination with\n * AV_OPT_SEARCH_FAKE_OBJ for examining options.\n *\n * @see av_opt_find().\n * @return the AVClass of SwrContext\n */\nconst AVClass *swr_get_class(void);\n\n/**\n * @name SwrContext constructor functions\n * @{\n */\n\n/**\n * Allocate SwrContext.\n *\n * If you use this function you will need to set the parameters (manually or\n * with swr_alloc_set_opts2()) before calling swr_init().\n *\n * @see swr_alloc_set_opts2(), swr_init(), swr_free()\n * @return NULL on error, allocated context otherwise\n */\nstruct SwrContext *swr_alloc(void);\n\n/**\n * Initialize context after user parameters have been set.\n * @note The context must be configured using the AVOption API.\n *\n * @see av_opt_set_int()\n * @see av_opt_set_dict()\n *\n * @param[in,out]   s Swr context to initialize\n * @return AVERROR error code in case of failure.\n */\nint swr_init(struct SwrContext *s);\n\n/**\n * Check whether an swr context has been initialized or not.\n *\n * @param[in]       s Swr context to check\n * @see swr_init()\n * @return positive if it has been initialized, 0 if not initialized\n */\nint swr_is_initialized(struct SwrContext *s);\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n/**\n * Allocate SwrContext if needed and set/reset common parameters.\n *\n * This function does not require s to be allocated with swr_alloc(). On the\n * other hand, swr_alloc() can use swr_alloc_set_opts() to set the parameters\n * on the allocated context.\n *\n * @param s               existing Swr context if available, or NULL if not\n * @param out_ch_layout   output channel layout (AV_CH_LAYOUT_*)\n * @param out_sample_fmt  output sample format (AV_SAMPLE_FMT_*).\n * @param out_sample_rate output sample rate (frequency in Hz)\n * @param in_ch_layout    input channel layout (AV_CH_LAYOUT_*)\n * @param in_sample_fmt   input sample format (AV_SAMPLE_FMT_*).\n * @param in_sample_rate  input sample rate (frequency in Hz)\n * @param log_offset      logging level offset\n * @param log_ctx         parent logging context, can be NULL\n *\n * @see swr_init(), swr_free()\n * @return NULL on error, allocated context otherwise\n * @deprecated use @ref swr_alloc_set_opts2()\n */\nattribute_deprecated\nstruct SwrContext *swr_alloc_set_opts(struct SwrContext *s,\n                                      int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,\n                                      int64_t  in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,\n                                      int log_offset, void *log_ctx);\n#endif\n\n/**\n * Allocate SwrContext if needed and set/reset common parameters.\n *\n * This function does not require *ps to be allocated with swr_alloc(). On the\n * other hand, swr_alloc() can use swr_alloc_set_opts2() to set the parameters\n * on the allocated context.\n *\n * @param ps              Pointer to an existing Swr context if available, or to NULL if not.\n *                        On success, *ps will be set to the allocated context.\n * @param out_ch_layout   output channel layout (e.g. AV_CHANNEL_LAYOUT_*)\n * @param out_sample_fmt  output sample format (AV_SAMPLE_FMT_*).\n * @param out_sample_rate output sample rate (frequency in Hz)\n * @param in_ch_layout    input channel layout (e.g. AV_CHANNEL_LAYOUT_*)\n * @param in_sample_fmt   input sample format (AV_SAMPLE_FMT_*).\n * @param in_sample_rate  input sample rate (frequency in Hz)\n * @param log_offset      logging level offset\n * @param log_ctx         parent logging context, can be NULL\n *\n * @see swr_init(), swr_free()\n * @return 0 on success, a negative AVERROR code on error.\n *         On error, the Swr context is freed and *ps set to NULL.\n */\nint swr_alloc_set_opts2(struct SwrContext **ps,\n                        AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,\n                        AVChannelLayout *in_ch_layout, enum AVSampleFormat  in_sample_fmt, int  in_sample_rate,\n                        int log_offset, void *log_ctx);\n/**\n * @}\n *\n * @name SwrContext destructor functions\n * @{\n */\n\n/**\n * Free the given SwrContext and set the pointer to NULL.\n *\n * @param[in] s a pointer to a pointer to Swr context\n */\nvoid swr_free(struct SwrContext **s);\n\n/**\n * Closes the context so that swr_is_initialized() returns 0.\n *\n * The context can be brought back to life by running swr_init(),\n * swr_init() can also be used without swr_close().\n * This function is mainly provided for simplifying the usecase\n * where one tries to support libavresample and libswresample.\n *\n * @param[in,out] s Swr context to be closed\n */\nvoid swr_close(struct SwrContext *s);\n\n/**\n * @}\n *\n * @name Core conversion functions\n * @{\n */\n\n/** Convert audio.\n *\n * in and in_count can be set to 0 to flush the last few samples out at the\n * end.\n *\n * If more input is provided than output space, then the input will be buffered.\n * You can avoid this buffering by using swr_get_out_samples() to retrieve an\n * upper bound on the required number of output samples for the given number of\n * input samples. Conversion will run directly without copying whenever possible.\n *\n * @param s         allocated Swr context, with parameters set\n * @param out       output buffers, only the first one need be set in case of packed audio\n * @param out_count amount of space available for output in samples per channel\n * @param in        input buffers, only the first one need to be set in case of packed audio\n * @param in_count  number of input samples available in one channel\n *\n * @return number of samples output per channel, negative value on error\n */\nint swr_convert(struct SwrContext *s, uint8_t **out, int out_count,\n                                const uint8_t **in , int in_count);\n\n/**\n * Convert the next timestamp from input to output\n * timestamps are in 1/(in_sample_rate * out_sample_rate) units.\n *\n * @note There are 2 slightly differently behaving modes.\n *       @li When automatic timestamp compensation is not used, (min_compensation >= FLT_MAX)\n *              in this case timestamps will be passed through with delays compensated\n *       @li When automatic timestamp compensation is used, (min_compensation < FLT_MAX)\n *              in this case the output timestamps will match output sample numbers.\n *              See ffmpeg-resampler(1) for the two modes of compensation.\n *\n * @param s[in]     initialized Swr context\n * @param pts[in]   timestamp for the next input sample, INT64_MIN if unknown\n * @see swr_set_compensation(), swr_drop_output(), and swr_inject_silence() are\n *      function used internally for timestamp compensation.\n * @return the output timestamp for the next output sample\n */\nint64_t swr_next_pts(struct SwrContext *s, int64_t pts);\n\n/**\n * @}\n *\n * @name Low-level option setting functions\n * These functons provide a means to set low-level options that is not possible\n * with the AVOption API.\n * @{\n */\n\n/**\n * Activate resampling compensation (\"soft\" compensation). This function is\n * internally called when needed in swr_next_pts().\n *\n * @param[in,out] s             allocated Swr context. If it is not initialized,\n *                              or SWR_FLAG_RESAMPLE is not set, swr_init() is\n *                              called with the flag set.\n * @param[in]     sample_delta  delta in PTS per sample\n * @param[in]     compensation_distance number of samples to compensate for\n * @return    >= 0 on success, AVERROR error codes if:\n *            @li @c s is NULL,\n *            @li @c compensation_distance is less than 0,\n *            @li @c compensation_distance is 0 but sample_delta is not,\n *            @li compensation unsupported by resampler, or\n *            @li swr_init() fails when called.\n */\nint swr_set_compensation(struct SwrContext *s, int sample_delta, int compensation_distance);\n\n/**\n * Set a customized input channel mapping.\n *\n * @param[in,out] s           allocated Swr context, not yet initialized\n * @param[in]     channel_map customized input channel mapping (array of channel\n *                            indexes, -1 for a muted channel)\n * @return >= 0 on success, or AVERROR error code in case of failure.\n */\nint swr_set_channel_mapping(struct SwrContext *s, const int *channel_map);\n\n#if FF_API_OLD_CHANNEL_LAYOUT\n/**\n * Generate a channel mixing matrix.\n *\n * This function is the one used internally by libswresample for building the\n * default mixing matrix. It is made public just as a utility function for\n * building custom matrices.\n *\n * @param in_layout           input channel layout\n * @param out_layout          output channel layout\n * @param center_mix_level    mix level for the center channel\n * @param surround_mix_level  mix level for the surround channel(s)\n * @param lfe_mix_level       mix level for the low-frequency effects channel\n * @param rematrix_maxval     if 1.0, coefficients will be normalized to prevent\n *                            overflow. if INT_MAX, coefficients will not be\n *                            normalized.\n * @param[out] matrix         mixing coefficients; matrix[i + stride * o] is\n *                            the weight of input channel i in output channel o.\n * @param stride              distance between adjacent input channels in the\n *                            matrix array\n * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)\n * @param log_ctx             parent logging context, can be NULL\n * @return                    0 on success, negative AVERROR code on failure\n * @deprecated                use @ref swr_build_matrix2()\n */\nattribute_deprecated\nint swr_build_matrix(uint64_t in_layout, uint64_t out_layout,\n                     double center_mix_level, double surround_mix_level,\n                     double lfe_mix_level, double rematrix_maxval,\n                     double rematrix_volume, double *matrix,\n                     int stride, enum AVMatrixEncoding matrix_encoding,\n                     void *log_ctx);\n#endif\n\n/**\n * Generate a channel mixing matrix.\n *\n * This function is the one used internally by libswresample for building the\n * default mixing matrix. It is made public just as a utility function for\n * building custom matrices.\n *\n * @param in_layout           input channel layout\n * @param out_layout          output channel layout\n * @param center_mix_level    mix level for the center channel\n * @param surround_mix_level  mix level for the surround channel(s)\n * @param lfe_mix_level       mix level for the low-frequency effects channel\n * @param rematrix_maxval     if 1.0, coefficients will be normalized to prevent\n *                            overflow. if INT_MAX, coefficients will not be\n *                            normalized.\n * @param[out] matrix         mixing coefficients; matrix[i + stride * o] is\n *                            the weight of input channel i in output channel o.\n * @param stride              distance between adjacent input channels in the\n *                            matrix array\n * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)\n * @param log_ctx             parent logging context, can be NULL\n * @return                    0 on success, negative AVERROR code on failure\n */\nint swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout,\n                      double center_mix_level, double surround_mix_level,\n                      double lfe_mix_level, double maxval,\n                      double rematrix_volume, double *matrix,\n                      ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding,\n                      void *log_context);\n\n/**\n * Set a customized remix matrix.\n *\n * @param s       allocated Swr context, not yet initialized\n * @param matrix  remix coefficients; matrix[i + stride * o] is\n *                the weight of input channel i in output channel o\n * @param stride  offset between lines of the matrix\n * @return  >= 0 on success, or AVERROR error code in case of failure.\n */\nint swr_set_matrix(struct SwrContext *s, const double *matrix, int stride);\n\n/**\n * @}\n *\n * @name Sample handling functions\n * @{\n */\n\n/**\n * Drops the specified number of output samples.\n *\n * This function, along with swr_inject_silence(), is called by swr_next_pts()\n * if needed for \"hard\" compensation.\n *\n * @param s     allocated Swr context\n * @param count number of samples to be dropped\n *\n * @return >= 0 on success, or a negative AVERROR code on failure\n */\nint swr_drop_output(struct SwrContext *s, int count);\n\n/**\n * Injects the specified number of silence samples.\n *\n * This function, along with swr_drop_output(), is called by swr_next_pts()\n * if needed for \"hard\" compensation.\n *\n * @param s     allocated Swr context\n * @param count number of samples to be dropped\n *\n * @return >= 0 on success, or a negative AVERROR code on failure\n */\nint swr_inject_silence(struct SwrContext *s, int count);\n\n/**\n * Gets the delay the next input sample will experience relative to the next output sample.\n *\n * Swresample can buffer data if more input has been provided than available\n * output space, also converting between sample rates needs a delay.\n * This function returns the sum of all such delays.\n * The exact delay is not necessarily an integer value in either input or\n * output sample rate. Especially when downsampling by a large value, the\n * output sample rate may be a poor choice to represent the delay, similarly\n * for upsampling and the input sample rate.\n *\n * @param s     swr context\n * @param base  timebase in which the returned delay will be:\n *              @li if it's set to 1 the returned delay is in seconds\n *              @li if it's set to 1000 the returned delay is in milliseconds\n *              @li if it's set to the input sample rate then the returned\n *                  delay is in input samples\n *              @li if it's set to the output sample rate then the returned\n *                  delay is in output samples\n *              @li if it's the least common multiple of in_sample_rate and\n *                  out_sample_rate then an exact rounding-free delay will be\n *                  returned\n * @returns     the delay in 1 / @c base units.\n */\nint64_t swr_get_delay(struct SwrContext *s, int64_t base);\n\n/**\n * Find an upper bound on the number of samples that the next swr_convert\n * call will output, if called with in_samples of input samples. This\n * depends on the internal state, and anything changing the internal state\n * (like further swr_convert() calls) will may change the number of samples\n * swr_get_out_samples() returns for the same number of input samples.\n *\n * @param in_samples    number of input samples.\n * @note any call to swr_inject_silence(), swr_convert(), swr_next_pts()\n *       or swr_set_compensation() invalidates this limit\n * @note it is recommended to pass the correct available buffer size\n *       to all functions like swr_convert() even if swr_get_out_samples()\n *       indicates that less would be used.\n * @returns an upper bound on the number of samples that the next swr_convert\n *          will output or a negative value to indicate an error\n */\nint swr_get_out_samples(struct SwrContext *s, int in_samples);\n\n/**\n * @}\n *\n * @name Configuration accessors\n * @{\n */\n\n/**\n * Return the @ref LIBSWRESAMPLE_VERSION_INT constant.\n *\n * This is useful to check if the build-time libswresample has the same version\n * as the run-time one.\n *\n * @returns     the unsigned int-typed version\n */\nunsigned swresample_version(void);\n\n/**\n * Return the swr build-time configuration.\n *\n * @returns     the build-time @c ./configure flags\n */\nconst char *swresample_configuration(void);\n\n/**\n * Return the swr license.\n *\n * @returns     the license of libswresample, determined at build-time\n */\nconst char *swresample_license(void);\n\n/**\n * @}\n *\n * @name AVFrame based API\n * @{\n */\n\n/**\n * Convert the samples in the input AVFrame and write them to the output AVFrame.\n *\n * Input and output AVFrames must have channel_layout, sample_rate and format set.\n *\n * If the output AVFrame does not have the data pointers allocated the nb_samples\n * field will be set using av_frame_get_buffer()\n * is called to allocate the frame.\n *\n * The output AVFrame can be NULL or have fewer allocated samples than required.\n * In this case, any remaining samples not written to the output will be added\n * to an internal FIFO buffer, to be returned at the next call to this function\n * or to swr_convert().\n *\n * If converting sample rate, there may be data remaining in the internal\n * resampling delay buffer. swr_get_delay() tells the number of\n * remaining samples. To get this data as output, call this function or\n * swr_convert() with NULL input.\n *\n * If the SwrContext configuration does not match the output and\n * input AVFrame settings the conversion does not take place and depending on\n * which AVFrame is not matching AVERROR_OUTPUT_CHANGED, AVERROR_INPUT_CHANGED\n * or the result of a bitwise-OR of them is returned.\n *\n * @see swr_delay()\n * @see swr_convert()\n * @see swr_get_delay()\n *\n * @param swr             audio resample context\n * @param output          output AVFrame\n * @param input           input AVFrame\n * @return                0 on success, AVERROR on failure or nonmatching\n *                        configuration.\n */\nint swr_convert_frame(SwrContext *swr,\n                      AVFrame *output, const AVFrame *input);\n\n/**\n * Configure or reconfigure the SwrContext using the information\n * provided by the AVFrames.\n *\n * The original resampling context is reset even on failure.\n * The function calls swr_close() internally if the context is open.\n *\n * @see swr_close();\n *\n * @param swr             audio resample context\n * @param output          output AVFrame\n * @param input           input AVFrame\n * @return                0 on success, AVERROR on failure.\n */\nint swr_config_frame(SwrContext *swr, const AVFrame *out, const AVFrame *in);\n\n/**\n * @}\n * @}\n */\n\n#endif /* SWRESAMPLE_SWRESAMPLE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libswresample/version.h",
    "content": "/*\n * Version macros.\n *\n * This file is part of libswresample\n *\n * libswresample is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * libswresample is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with libswresample; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef SWRESAMPLE_VERSION_H\n#define SWRESAMPLE_VERSION_H\n\n/**\n * @file\n * Libswresample version macros\n */\n\n#include \"libavutil/version.h\"\n\n#include \"version_major.h\"\n\n#define LIBSWRESAMPLE_VERSION_MINOR   7\n#define LIBSWRESAMPLE_VERSION_MICRO 100\n\n#define LIBSWRESAMPLE_VERSION_INT  AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \\\n                                                  LIBSWRESAMPLE_VERSION_MINOR, \\\n                                                  LIBSWRESAMPLE_VERSION_MICRO)\n#define LIBSWRESAMPLE_VERSION      AV_VERSION(LIBSWRESAMPLE_VERSION_MAJOR, \\\n                                              LIBSWRESAMPLE_VERSION_MINOR, \\\n                                              LIBSWRESAMPLE_VERSION_MICRO)\n#define LIBSWRESAMPLE_BUILD        LIBSWRESAMPLE_VERSION_INT\n\n#define LIBSWRESAMPLE_IDENT        \"SwR\" AV_STRINGIFY(LIBSWRESAMPLE_VERSION)\n\n#endif /* SWRESAMPLE_VERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libswresample/version_major.h",
    "content": "/*\n * Version macros.\n *\n * This file is part of libswresample\n *\n * libswresample is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * libswresample is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with libswresample; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef SWRESAMPLE_VERSION_MAJOR_H\n#define SWRESAMPLE_VERSION_MAJOR_H\n\n/**\n * @file\n * Libswresample version macros\n */\n\n#define LIBSWRESAMPLE_VERSION_MAJOR   4\n\n#endif /* SWRESAMPLE_VERSION_MAJOR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libswscale/swscale.h",
    "content": "/*\n * Copyright (C) 2001-2011 Michael Niedermayer <michaelni@gmx.at>\n *\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef SWSCALE_SWSCALE_H\n#define SWSCALE_SWSCALE_H\n\n/**\n * @file\n * @ingroup libsws\n * external API header\n */\n\n#include <stdint.h>\n\n#include \"libavutil/avutil.h\"\n#include \"libavutil/frame.h\"\n#include \"libavutil/log.h\"\n#include \"libavutil/pixfmt.h\"\n#include \"version_major.h\"\n#ifndef HAVE_AV_CONFIG_H\n/* When included as part of the ffmpeg build, only include the major version\n * to avoid unnecessary rebuilds. When included externally, keep including\n * the full version information. */\n#include \"version.h\"\n#endif\n\n/**\n * @defgroup libsws libswscale\n * Color conversion and scaling library.\n *\n * @{\n *\n * Return the LIBSWSCALE_VERSION_INT constant.\n */\nunsigned swscale_version(void);\n\n/**\n * Return the libswscale build-time configuration.\n */\nconst char *swscale_configuration(void);\n\n/**\n * Return the libswscale license.\n */\nconst char *swscale_license(void);\n\n/* values for the flags, the stuff on the command line is different */\n#define SWS_FAST_BILINEAR     1\n#define SWS_BILINEAR          2\n#define SWS_BICUBIC           4\n#define SWS_X                 8\n#define SWS_POINT          0x10\n#define SWS_AREA           0x20\n#define SWS_BICUBLIN       0x40\n#define SWS_GAUSS          0x80\n#define SWS_SINC          0x100\n#define SWS_LANCZOS       0x200\n#define SWS_SPLINE        0x400\n\n#define SWS_SRC_V_CHR_DROP_MASK     0x30000\n#define SWS_SRC_V_CHR_DROP_SHIFT    16\n\n#define SWS_PARAM_DEFAULT           123456\n\n#define SWS_PRINT_INFO              0x1000\n\n//the following 3 flags are not completely implemented\n//internal chrominance subsampling info\n#define SWS_FULL_CHR_H_INT    0x2000\n//input subsampling info\n#define SWS_FULL_CHR_H_INP    0x4000\n#define SWS_DIRECT_BGR        0x8000\n#define SWS_ACCURATE_RND      0x40000\n#define SWS_BITEXACT          0x80000\n#define SWS_ERROR_DIFFUSION  0x800000\n\n#define SWS_MAX_REDUCE_CUTOFF 0.002\n\n#define SWS_CS_ITU709         1\n#define SWS_CS_FCC            4\n#define SWS_CS_ITU601         5\n#define SWS_CS_ITU624         5\n#define SWS_CS_SMPTE170M      5\n#define SWS_CS_SMPTE240M      7\n#define SWS_CS_DEFAULT        5\n#define SWS_CS_BT2020         9\n\n/**\n * Return a pointer to yuv<->rgb coefficients for the given colorspace\n * suitable for sws_setColorspaceDetails().\n *\n * @param colorspace One of the SWS_CS_* macros. If invalid,\n * SWS_CS_DEFAULT is used.\n */\nconst int *sws_getCoefficients(int colorspace);\n\n// when used for filters they must have an odd number of elements\n// coeffs cannot be shared between vectors\ntypedef struct SwsVector {\n    double *coeff;              ///< pointer to the list of coefficients\n    int length;                 ///< number of coefficients in the vector\n} SwsVector;\n\n// vectors can be shared\ntypedef struct SwsFilter {\n    SwsVector *lumH;\n    SwsVector *lumV;\n    SwsVector *chrH;\n    SwsVector *chrV;\n} SwsFilter;\n\nstruct SwsContext;\n\n/**\n * Return a positive value if pix_fmt is a supported input format, 0\n * otherwise.\n */\nint sws_isSupportedInput(enum AVPixelFormat pix_fmt);\n\n/**\n * Return a positive value if pix_fmt is a supported output format, 0\n * otherwise.\n */\nint sws_isSupportedOutput(enum AVPixelFormat pix_fmt);\n\n/**\n * @param[in]  pix_fmt the pixel format\n * @return a positive value if an endianness conversion for pix_fmt is\n * supported, 0 otherwise.\n */\nint sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt);\n\n/**\n * Allocate an empty SwsContext. This must be filled and passed to\n * sws_init_context(). For filling see AVOptions, options.c and\n * sws_setColorspaceDetails().\n */\nstruct SwsContext *sws_alloc_context(void);\n\n/**\n * Initialize the swscaler context sws_context.\n *\n * @return zero or positive value on success, a negative value on\n * error\n */\nav_warn_unused_result\nint sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter);\n\n/**\n * Free the swscaler context swsContext.\n * If swsContext is NULL, then does nothing.\n */\nvoid sws_freeContext(struct SwsContext *swsContext);\n\n/**\n * Allocate and return an SwsContext. You need it to perform\n * scaling/conversion operations using sws_scale().\n *\n * @param srcW the width of the source image\n * @param srcH the height of the source image\n * @param srcFormat the source image format\n * @param dstW the width of the destination image\n * @param dstH the height of the destination image\n * @param dstFormat the destination image format\n * @param flags specify which algorithm and options to use for rescaling\n * @param param extra parameters to tune the used scaler\n *              For SWS_BICUBIC param[0] and [1] tune the shape of the basis\n *              function, param[0] tunes f(1) and param[1] f´(1)\n *              For SWS_GAUSS param[0] tunes the exponent and thus cutoff\n *              frequency\n *              For SWS_LANCZOS param[0] tunes the width of the window function\n * @return a pointer to an allocated context, or NULL in case of error\n * @note this function is to be removed after a saner alternative is\n *       written\n */\nstruct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,\n                                  int dstW, int dstH, enum AVPixelFormat dstFormat,\n                                  int flags, SwsFilter *srcFilter,\n                                  SwsFilter *dstFilter, const double *param);\n\n/**\n * Scale the image slice in srcSlice and put the resulting scaled\n * slice in the image in dst. A slice is a sequence of consecutive\n * rows in an image.\n *\n * Slices have to be provided in sequential order, either in\n * top-bottom or bottom-top order. If slices are provided in\n * non-sequential order the behavior of the function is undefined.\n *\n * @param c         the scaling context previously created with\n *                  sws_getContext()\n * @param srcSlice  the array containing the pointers to the planes of\n *                  the source slice\n * @param srcStride the array containing the strides for each plane of\n *                  the source image\n * @param srcSliceY the position in the source image of the slice to\n *                  process, that is the number (counted starting from\n *                  zero) in the image of the first row of the slice\n * @param srcSliceH the height of the source slice, that is the number\n *                  of rows in the slice\n * @param dst       the array containing the pointers to the planes of\n *                  the destination image\n * @param dstStride the array containing the strides for each plane of\n *                  the destination image\n * @return          the height of the output slice\n */\nint sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],\n              const int srcStride[], int srcSliceY, int srcSliceH,\n              uint8_t *const dst[], const int dstStride[]);\n\n/**\n * Scale source data from src and write the output to dst.\n *\n * This is merely a convenience wrapper around\n * - sws_frame_start()\n * - sws_send_slice(0, src->height)\n * - sws_receive_slice(0, dst->height)\n * - sws_frame_end()\n *\n * @param dst The destination frame. See documentation for sws_frame_start() for\n *            more details.\n * @param src The source frame.\n *\n * @return 0 on success, a negative AVERROR code on failure\n */\nint sws_scale_frame(struct SwsContext *c, AVFrame *dst, const AVFrame *src);\n\n/**\n * Initialize the scaling process for a given pair of source/destination frames.\n * Must be called before any calls to sws_send_slice() and sws_receive_slice().\n *\n * This function will retain references to src and dst, so they must both use\n * refcounted buffers (if allocated by the caller, in case of dst).\n *\n * @param dst The destination frame.\n *\n *            The data buffers may either be already allocated by the caller or\n *            left clear, in which case they will be allocated by the scaler.\n *            The latter may have performance advantages - e.g. in certain cases\n *            some output planes may be references to input planes, rather than\n *            copies.\n *\n *            Output data will be written into this frame in successful\n *            sws_receive_slice() calls.\n * @param src The source frame. The data buffers must be allocated, but the\n *            frame data does not have to be ready at this point. Data\n *            availability is then signalled by sws_send_slice().\n * @return 0 on success, a negative AVERROR code on failure\n *\n * @see sws_frame_end()\n */\nint sws_frame_start(struct SwsContext *c, AVFrame *dst, const AVFrame *src);\n\n/**\n * Finish the scaling process for a pair of source/destination frames previously\n * submitted with sws_frame_start(). Must be called after all sws_send_slice()\n * and sws_receive_slice() calls are done, before any new sws_frame_start()\n * calls.\n */\nvoid sws_frame_end(struct SwsContext *c);\n\n/**\n * Indicate that a horizontal slice of input data is available in the source\n * frame previously provided to sws_frame_start(). The slices may be provided in\n * any order, but may not overlap. For vertically subsampled pixel formats, the\n * slices must be aligned according to subsampling.\n *\n * @param slice_start first row of the slice\n * @param slice_height number of rows in the slice\n *\n * @return a non-negative number on success, a negative AVERROR code on failure.\n */\nint sws_send_slice(struct SwsContext *c, unsigned int slice_start,\n                   unsigned int slice_height);\n\n/**\n * Request a horizontal slice of the output data to be written into the frame\n * previously provided to sws_frame_start().\n *\n * @param slice_start first row of the slice; must be a multiple of\n *                    sws_receive_slice_alignment()\n * @param slice_height number of rows in the slice; must be a multiple of\n *                     sws_receive_slice_alignment(), except for the last slice\n *                     (i.e. when slice_start+slice_height is equal to output\n *                     frame height)\n *\n * @return a non-negative number if the data was successfully written into the output\n *         AVERROR(EAGAIN) if more input data needs to be provided before the\n *                         output can be produced\n *         another negative AVERROR code on other kinds of scaling failure\n */\nint sws_receive_slice(struct SwsContext *c, unsigned int slice_start,\n                      unsigned int slice_height);\n\n/**\n * @return alignment required for output slices requested with sws_receive_slice().\n *         Slice offsets and sizes passed to sws_receive_slice() must be\n *         multiples of the value returned from this function.\n */\nunsigned int sws_receive_slice_alignment(const struct SwsContext *c);\n\n/**\n * @param dstRange flag indicating the while-black range of the output (1=jpeg / 0=mpeg)\n * @param srcRange flag indicating the while-black range of the input (1=jpeg / 0=mpeg)\n * @param table the yuv2rgb coefficients describing the output yuv space, normally ff_yuv2rgb_coeffs[x]\n * @param inv_table the yuv2rgb coefficients describing the input yuv space, normally ff_yuv2rgb_coeffs[x]\n * @param brightness 16.16 fixed point brightness correction\n * @param contrast 16.16 fixed point contrast correction\n * @param saturation 16.16 fixed point saturation correction\n#if LIBSWSCALE_VERSION_MAJOR > 6\n * @return negative error code on error, non negative otherwise\n#else\n * @return -1 if not supported\n#endif\n */\nint sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],\n                             int srcRange, const int table[4], int dstRange,\n                             int brightness, int contrast, int saturation);\n\n/**\n#if LIBSWSCALE_VERSION_MAJOR > 6\n * @return negative error code on error, non negative otherwise\n#else\n * @return -1 if not supported\n#endif\n */\nint sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,\n                             int *srcRange, int **table, int *dstRange,\n                             int *brightness, int *contrast, int *saturation);\n\n/**\n * Allocate and return an uninitialized vector with length coefficients.\n */\nSwsVector *sws_allocVec(int length);\n\n/**\n * Return a normalized Gaussian curve used to filter stuff\n * quality = 3 is high quality, lower is lower quality.\n */\nSwsVector *sws_getGaussianVec(double variance, double quality);\n\n/**\n * Scale all the coefficients of a by the scalar value.\n */\nvoid sws_scaleVec(SwsVector *a, double scalar);\n\n/**\n * Scale all the coefficients of a so that their sum equals height.\n */\nvoid sws_normalizeVec(SwsVector *a, double height);\n\nvoid sws_freeVec(SwsVector *a);\n\nSwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,\n                                float lumaSharpen, float chromaSharpen,\n                                float chromaHShift, float chromaVShift,\n                                int verbose);\nvoid sws_freeFilter(SwsFilter *filter);\n\n/**\n * Check if context can be reused, otherwise reallocate a new one.\n *\n * If context is NULL, just calls sws_getContext() to get a new\n * context. Otherwise, checks if the parameters are the ones already\n * saved in context. If that is the case, returns the current\n * context. Otherwise, frees context and gets a new context with\n * the new parameters.\n *\n * Be warned that srcFilter and dstFilter are not checked, they\n * are assumed to remain the same.\n */\nstruct SwsContext *sws_getCachedContext(struct SwsContext *context,\n                                        int srcW, int srcH, enum AVPixelFormat srcFormat,\n                                        int dstW, int dstH, enum AVPixelFormat dstFormat,\n                                        int flags, SwsFilter *srcFilter,\n                                        SwsFilter *dstFilter, const double *param);\n\n/**\n * Convert an 8-bit paletted frame into a frame with a color depth of 32 bits.\n *\n * The output frame will have the same packed format as the palette.\n *\n * @param src        source frame buffer\n * @param dst        destination frame buffer\n * @param num_pixels number of pixels to convert\n * @param palette    array with [256] entries, which must match color arrangement (RGB or BGR) of src\n */\nvoid sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette);\n\n/**\n * Convert an 8-bit paletted frame into a frame with a color depth of 24 bits.\n *\n * With the palette format \"ABCD\", the destination frame ends up with the format \"ABC\".\n *\n * @param src        source frame buffer\n * @param dst        destination frame buffer\n * @param num_pixels number of pixels to convert\n * @param palette    array with [256] entries, which must match color arrangement (RGB or BGR) of src\n */\nvoid sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette);\n\n/**\n * Get the AVClass for swsContext. It can be used in combination with\n * AV_OPT_SEARCH_FAKE_OBJ for examining options.\n *\n * @see av_opt_find().\n */\nconst AVClass *sws_get_class(void);\n\n/**\n * @}\n */\n\n#endif /* SWSCALE_SWSCALE_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libswscale/version.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef SWSCALE_VERSION_H\n#define SWSCALE_VERSION_H\n\n/**\n * @file\n * swscale version macros\n */\n\n#include \"libavutil/version.h\"\n\n#include \"version_major.h\"\n\n#define LIBSWSCALE_VERSION_MINOR   7\n#define LIBSWSCALE_VERSION_MICRO 100\n\n#define LIBSWSCALE_VERSION_INT  AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \\\n                                               LIBSWSCALE_VERSION_MINOR, \\\n                                               LIBSWSCALE_VERSION_MICRO)\n#define LIBSWSCALE_VERSION      AV_VERSION(LIBSWSCALE_VERSION_MAJOR, \\\n                                           LIBSWSCALE_VERSION_MINOR, \\\n                                           LIBSWSCALE_VERSION_MICRO)\n#define LIBSWSCALE_BUILD        LIBSWSCALE_VERSION_INT\n\n#define LIBSWSCALE_IDENT        \"SwS\" AV_STRINGIFY(LIBSWSCALE_VERSION)\n\n#endif /* SWSCALE_VERSION_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/include/libswscale/version_major.h",
    "content": "/*\n * This file is part of FFmpeg.\n *\n * FFmpeg is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * FFmpeg is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with FFmpeg; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n */\n\n#ifndef SWSCALE_VERSION_MAJOR_H\n#define SWSCALE_VERSION_MAJOR_H\n\n/**\n * @file\n * swscale version macros\n */\n\n#define LIBSWSCALE_VERSION_MAJOR   6\n\n/**\n * FF_API_* defines may be placed below to indicate public API that will be\n * dropped at a future version bump. The defines themselves are not part of\n * the public API and may change, break or disappear at any time.\n */\n\n#endif /* SWSCALE_VERSION_MAJOR_H */\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/lib/win/avcodec-59.def",
    "content": "EXPORTS\n    av_ac3_parse_header\n    av_adts_header_parse\n    av_bsf_alloc\n    av_bsf_flush\n    av_bsf_free\n    av_bsf_get_by_name\n    av_bsf_get_class\n    av_bsf_get_null_filter\n    av_bsf_init\n    av_bsf_iterate\n    av_bsf_list_alloc\n    av_bsf_list_append\n    av_bsf_list_append2\n    av_bsf_list_finalize\n    av_bsf_list_free\n    av_bsf_list_parse_str\n    av_bsf_receive_packet\n    av_bsf_send_packet\n    av_codec_ffversion\n    av_codec_is_decoder\n    av_codec_is_encoder\n    av_codec_iterate\n    av_cpb_properties_alloc\n    av_d3d11va_alloc_context\n    av_dct_calc\n    av_dct_end\n    av_dct_init\n    av_dirac_parse_sequence_header\n    av_dv_codec_profile\n    av_dv_codec_profile2\n    av_dv_frame_profile\n    av_fast_padded_malloc\n    av_fast_padded_mallocz\n    av_fft_calc\n    av_fft_end\n    av_fft_init\n    av_fft_permute\n    av_get_audio_frame_duration\n    av_get_audio_frame_duration2\n    av_get_bits_per_sample\n    av_get_exact_bits_per_sample\n    av_get_pcm_codec\n    av_get_profile_name\n    av_grow_packet\n    av_imdct_calc\n    av_imdct_half\n    av_init_packet\n    av_jni_get_java_vm\n    av_jni_set_java_vm\n    av_mdct_calc\n    av_mdct_end\n    av_mdct_init\n    av_mediacodec_alloc_context\n    av_mediacodec_default_free\n    av_mediacodec_default_init\n    av_mediacodec_release_buffer\n    av_mediacodec_render_buffer_at_time\n    av_new_packet\n    av_packet_add_side_data\n    av_packet_alloc\n    av_packet_clone\n    av_packet_copy_props\n    av_packet_free\n    av_packet_free_side_data\n    av_packet_from_data\n    av_packet_get_side_data\n    av_packet_make_refcounted\n    av_packet_make_writable\n    av_packet_move_ref\n    av_packet_new_side_data\n    av_packet_pack_dictionary\n    av_packet_ref\n    av_packet_rescale_ts\n    av_packet_shrink_side_data\n    av_packet_side_data_name\n    av_packet_unpack_dictionary\n    av_packet_unref\n    av_parser_close\n    av_parser_init\n    av_parser_iterate\n    av_parser_parse2\n    av_qsv_alloc_context\n    av_rdft_calc\n    av_rdft_end\n    av_rdft_init\n    av_shrink_packet\n    av_vorbis_parse_frame\n    av_vorbis_parse_frame_flags\n    av_vorbis_parse_free\n    av_vorbis_parse_init\n    av_vorbis_parse_reset\n    av_xiphlacing\n    avcodec_align_dimensions\n    avcodec_align_dimensions2\n    avcodec_alloc_context3\n    avcodec_chroma_pos_to_enum\n    avcodec_close\n    avcodec_configuration\n    avcodec_dct_alloc\n    avcodec_dct_get_class\n    avcodec_dct_init\n    avcodec_decode_subtitle2\n    avcodec_default_execute\n    avcodec_default_execute2\n    avcodec_default_get_buffer2\n    avcodec_default_get_encode_buffer\n    avcodec_default_get_format\n    avcodec_descriptor_get\n    avcodec_descriptor_get_by_name\n    avcodec_descriptor_next\n    avcodec_encode_subtitle\n    avcodec_enum_to_chroma_pos\n    avcodec_fill_audio_frame\n    avcodec_find_best_pix_fmt_of_list\n    avcodec_find_decoder\n    avcodec_find_decoder_by_name\n    avcodec_find_encoder\n    avcodec_find_encoder_by_name\n    avcodec_flush_buffers\n    avcodec_free_context\n    avcodec_get_class\n    avcodec_get_frame_class\n    avcodec_get_hw_config\n    avcodec_get_hw_frames_parameters\n    avcodec_get_name\n    avcodec_get_subtitle_rect_class\n    avcodec_get_type\n    avcodec_is_open\n    avcodec_license\n    avcodec_open2\n    avcodec_parameters_alloc\n    avcodec_parameters_copy\n    avcodec_parameters_free\n    avcodec_parameters_from_context\n    avcodec_parameters_to_context\n    avcodec_pix_fmt_to_codec_tag\n    avcodec_profile_name\n    avcodec_receive_frame\n    avcodec_receive_packet\n    avcodec_send_frame\n    avcodec_send_packet\n    avcodec_string\n    avcodec_version\n    avpriv_ac3_parse_header\n    avpriv_adts_header_parse\n    avpriv_codec_get_cap_skip_frame_fill_param\n    avpriv_dca_convert_bitstream\n    avpriv_dca_parse_core_frame_header\n    avpriv_elbg_do\n    avpriv_elbg_free\n    avpriv_exif_decode_ifd\n    avpriv_find_start_code\n    avpriv_fits_header_init\n    avpriv_fits_header_parse_line\n    avpriv_get_raw_pix_fmt_tags\n    avpriv_h264_has_num_reorder_frames\n    avpriv_mpeg4audio_get_config2\n    avpriv_mpegaudio_decode_header\n    avpriv_packet_list_free\n    avpriv_packet_list_get\n    avpriv_packet_list_put\n    avpriv_pix_fmt_find\n    avpriv_split_xiph_headers\n    avpriv_tak_parse_streaminfo\n    avsubtitle_free\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/lib/win/avdevice-59.def",
    "content": "EXPORTS\n    av_device_capabilities\n    av_device_ffversion\n    av_input_audio_device_next\n    av_input_video_device_next\n    av_output_audio_device_next\n    av_output_video_device_next\n    avdevice_app_to_dev_control_message\n    avdevice_capabilities_create\n    avdevice_capabilities_free\n    avdevice_configuration\n    avdevice_dev_to_app_control_message\n    avdevice_free_list_devices\n    avdevice_license\n    avdevice_list_devices\n    avdevice_list_input_sources\n    avdevice_list_output_sinks\n    avdevice_register_all\n    avdevice_version\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/lib/win/avfilter-8.def",
    "content": "EXPORTS\n    av_abuffersink_params_alloc\n    av_buffersink_get_ch_layout\n    av_buffersink_get_channel_layout\n    av_buffersink_get_channels\n    av_buffersink_get_format\n    av_buffersink_get_frame\n    av_buffersink_get_frame_flags\n    av_buffersink_get_frame_rate\n    av_buffersink_get_h\n    av_buffersink_get_hw_frames_ctx\n    av_buffersink_get_sample_aspect_ratio\n    av_buffersink_get_sample_rate\n    av_buffersink_get_samples\n    av_buffersink_get_time_base\n    av_buffersink_get_type\n    av_buffersink_get_w\n    av_buffersink_params_alloc\n    av_buffersink_set_frame_size\n    av_buffersrc_add_frame\n    av_buffersrc_add_frame_flags\n    av_buffersrc_close\n    av_buffersrc_get_nb_failed_requests\n    av_buffersrc_parameters_alloc\n    av_buffersrc_parameters_set\n    av_buffersrc_write_frame\n    av_filter_ffversion\n    av_filter_iterate\n    avfilter_config_links\n    avfilter_configuration\n    avfilter_filter_pad_count\n    avfilter_free\n    avfilter_get_by_name\n    avfilter_get_class\n    avfilter_graph_alloc\n    avfilter_graph_alloc_filter\n    avfilter_graph_config\n    avfilter_graph_create_filter\n    avfilter_graph_dump\n    avfilter_graph_free\n    avfilter_graph_get_filter\n    avfilter_graph_parse\n    avfilter_graph_parse_ptr\n    avfilter_graph_parse2\n    avfilter_graph_queue_command\n    avfilter_graph_request_oldest\n    avfilter_graph_send_command\n    avfilter_graph_set_auto_convert\n    avfilter_init_dict\n    avfilter_init_str\n    avfilter_inout_alloc\n    avfilter_inout_free\n    avfilter_insert_filter\n    avfilter_license\n    avfilter_link\n    avfilter_link_free\n    avfilter_pad_count\n    avfilter_pad_get_name\n    avfilter_pad_get_type\n    avfilter_process_command\n    avfilter_version\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/lib/win/avformat-59.def",
    "content": "EXPORTS\n    av_add_index_entry\n    av_append_packet\n    av_codec_get_id\n    av_codec_get_tag\n    av_codec_get_tag2\n    av_demuxer_iterate\n    av_disposition_from_string\n    av_disposition_to_string\n    av_dump_format\n    av_filename_number_test\n    av_find_best_stream\n    av_find_default_stream_index\n    av_find_input_format\n    av_find_program_from_stream\n    av_fmt_ctx_get_duration_estimation_method\n    av_format_ffversion\n    av_format_inject_global_side_data\n    av_get_frame_filename\n    av_get_frame_filename2\n    av_get_output_timestamp\n    av_get_packet\n    av_guess_codec\n    av_guess_format\n    av_guess_frame_rate\n    av_guess_sample_aspect_ratio\n    av_hex_dump\n    av_hex_dump_log\n    av_index_search_timestamp\n    av_interleaved_write_frame\n    av_interleaved_write_uncoded_frame\n    av_match_ext\n    av_muxer_iterate\n    av_new_program\n    av_pkt_dump_log2\n    av_pkt_dump2\n    av_probe_input_buffer\n    av_probe_input_buffer2\n    av_probe_input_format\n    av_probe_input_format2\n    av_probe_input_format3\n    av_program_add_stream_index\n    av_read_frame\n    av_read_pause\n    av_read_play\n    av_sdp_create\n    av_seek_frame\n    av_stream_add_side_data\n    av_stream_get_class\n    av_stream_get_codec_timebase\n    av_stream_get_end_pts\n    av_stream_get_parser\n    av_stream_get_side_data\n    av_stream_new_side_data\n    av_url_split\n    av_write_frame\n    av_write_trailer\n    av_write_uncoded_frame\n    av_write_uncoded_frame_query\n    avformat_alloc_context\n    avformat_alloc_output_context2\n    avformat_close_input\n    avformat_configuration\n    avformat_find_stream_info\n    avformat_flush\n    avformat_free_context\n    avformat_get_class\n    avformat_get_mov_audio_tags\n    avformat_get_mov_video_tags\n    avformat_get_riff_audio_tags\n    avformat_get_riff_video_tags\n    avformat_index_get_entries_count\n    avformat_index_get_entry\n    avformat_index_get_entry_from_timestamp\n    avformat_init_output\n    avformat_license\n    avformat_match_stream_specifier\n    avformat_network_deinit\n    avformat_network_init\n    avformat_new_stream\n    avformat_open_input\n    avformat_query_codec\n    avformat_queue_attached_pictures\n    avformat_seek_file\n    avformat_transfer_internal_stream_timing_info\n    avformat_version\n    avformat_write_header\n    avio_accept\n    avio_alloc_context\n    avio_check\n    avio_close\n    avio_close_dir\n    avio_close_dyn_buf\n    avio_closep\n    avio_context_free\n    avio_enum_protocols\n    avio_feof\n    avio_find_protocol_name\n    avio_flush\n    avio_free_directory_entry\n    avio_get_dyn_buf\n    avio_get_str\n    avio_get_str16be\n    avio_get_str16le\n    avio_handshake\n    avio_open\n    avio_open_dir\n    avio_open_dyn_buf\n    avio_open2\n    avio_pause\n    avio_print_string_array\n    avio_printf\n    avio_protocol_get_class\n    avio_put_str\n    avio_put_str16be\n    avio_put_str16le\n    avio_r8\n    avio_rb16\n    avio_rb24\n    avio_rb32\n    avio_rb64\n    avio_read\n    avio_read_dir\n    avio_read_partial\n    avio_read_to_bprint\n    avio_rl16\n    avio_rl24\n    avio_rl32\n    avio_rl64\n    avio_seek\n    avio_seek_time\n    avio_size\n    avio_skip\n    avio_vprintf\n    avio_w8\n    avio_wb16\n    avio_wb24\n    avio_wb32\n    avio_wb64\n    avio_wl16\n    avio_wl24\n    avio_wl32\n    avio_wl64\n    avio_write\n    avio_write_marker\n    avpriv_dv_get_packet\n    avpriv_dv_init_demux\n    avpriv_dv_produce_packet\n    avpriv_mpegts_parse_close\n    avpriv_mpegts_parse_open\n    avpriv_mpegts_parse_packet\n    avpriv_new_chapter\n    avpriv_register_devices\n    avpriv_set_pts_info\n    avpriv_stream_set_need_parsing\n    avpriv_update_cur_dts\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/lib/win/avutil-57.def",
    "content": "EXPORTS\n    av_add_i\n    av_add_q\n    av_add_stable\n    av_adler32_update\n    av_aes_alloc\n    av_aes_crypt\n    av_aes_ctr_alloc\n    av_aes_ctr_crypt\n    av_aes_ctr_free\n    av_aes_ctr_get_iv\n    av_aes_ctr_increment_iv\n    av_aes_ctr_init\n    av_aes_ctr_set_full_iv\n    av_aes_ctr_set_iv\n    av_aes_ctr_set_random_iv\n    av_aes_init\n    av_aes_size\n    av_append_path_component\n    av_asprintf\n    av_assert0_fpu\n    av_audio_fifo_alloc\n    av_audio_fifo_drain\n    av_audio_fifo_free\n    av_audio_fifo_peek\n    av_audio_fifo_peek_at\n    av_audio_fifo_read\n    av_audio_fifo_realloc\n    av_audio_fifo_reset\n    av_audio_fifo_size\n    av_audio_fifo_space\n    av_audio_fifo_write\n    av_base64_decode\n    av_base64_encode\n    av_basename\n    av_blowfish_alloc\n    av_blowfish_crypt\n    av_blowfish_crypt_ecb\n    av_blowfish_init\n    av_bmg_get\n    av_bprint_append_data\n    av_bprint_channel_layout\n    av_bprint_chars\n    av_bprint_clear\n    av_bprint_escape\n    av_bprint_finalize\n    av_bprint_get_buffer\n    av_bprint_init\n    av_bprint_init_for_buffer\n    av_bprint_strftime\n    av_bprintf\n    av_buffer_alloc\n    av_buffer_allocz\n    av_buffer_create\n    av_buffer_default_free\n    av_buffer_get_opaque\n    av_buffer_get_ref_count\n    av_buffer_is_writable\n    av_buffer_make_writable\n    av_buffer_pool_buffer_get_opaque\n    av_buffer_pool_get\n    av_buffer_pool_init\n    av_buffer_pool_init2\n    av_buffer_pool_uninit\n    av_buffer_realloc\n    av_buffer_ref\n    av_buffer_replace\n    av_buffer_unref\n    av_calloc\n    av_camellia_alloc\n    av_camellia_crypt\n    av_camellia_init\n    av_camellia_size\n    av_cast5_alloc\n    av_cast5_crypt\n    av_cast5_crypt2\n    av_cast5_init\n    av_cast5_size\n    av_channel_description\n    av_channel_description_bprint\n    av_channel_from_string\n    av_channel_layout_channel_from_index\n    av_channel_layout_channel_from_string\n    av_channel_layout_check\n    av_channel_layout_compare\n    av_channel_layout_copy\n    av_channel_layout_default\n    av_channel_layout_describe\n    av_channel_layout_describe_bprint\n    av_channel_layout_extract_channel\n    av_channel_layout_from_mask\n    av_channel_layout_from_string\n    av_channel_layout_index_from_channel\n    av_channel_layout_index_from_string\n    av_channel_layout_standard\n    av_channel_layout_subset\n    av_channel_layout_uninit\n    av_channel_name\n    av_channel_name_bprint\n    av_chroma_location_from_name\n    av_chroma_location_name\n    av_cmp_i\n    av_color_primaries_from_name\n    av_color_primaries_name\n    av_color_range_from_name\n    av_color_range_name\n    av_color_space_from_name\n    av_color_space_name\n    av_color_transfer_from_name\n    av_color_transfer_name\n    av_compare_mod\n    av_compare_ts\n    av_content_light_metadata_alloc\n    av_content_light_metadata_create_side_data\n    av_cpu_count\n    av_cpu_force_count\n    av_cpu_max_align\n    av_crc\n    av_crc_get_table\n    av_crc_init\n    av_csp_luma_coeffs_from_avcsp\n    av_csp_primaries_desc_from_id\n    av_csp_primaries_id_from_desc\n    av_d2q\n    av_d2str\n    av_default_get_category\n    av_default_item_name\n    av_des_alloc\n    av_des_crypt\n    av_des_init\n    av_des_mac\n    av_detection_bbox_alloc\n    av_detection_bbox_create_side_data\n    av_dict_copy\n    av_dict_count\n    av_dict_free\n    av_dict_get\n    av_dict_get_string\n    av_dict_parse_string\n    av_dict_set\n    av_dict_set_int\n    av_dirname\n    av_display_matrix_flip\n    av_display_rotation_get\n    av_display_rotation_set\n    av_div_i\n    av_div_q\n    av_dovi_alloc\n    av_dovi_metadata_alloc\n    av_downmix_info_update_side_data\n    av_dynamic_hdr_plus_alloc\n    av_dynamic_hdr_plus_create_side_data\n    av_dynamic_hdr_vivid_alloc\n    av_dynamic_hdr_vivid_create_side_data\n    av_dynarray_add\n    av_dynarray_add_nofree\n    av_dynarray2_add\n    av_encryption_info_add_side_data\n    av_encryption_info_alloc\n    av_encryption_info_clone\n    av_encryption_info_free\n    av_encryption_info_get_side_data\n    av_encryption_init_info_add_side_data\n    av_encryption_init_info_alloc\n    av_encryption_init_info_free\n    av_encryption_init_info_get_side_data\n    av_escape\n    av_expr_count_func\n    av_expr_count_vars\n    av_expr_eval\n    av_expr_free\n    av_expr_parse\n    av_expr_parse_and_eval\n    av_fast_malloc\n    av_fast_mallocz\n    av_fast_realloc\n    av_fifo_alloc\n    av_fifo_alloc_array\n    av_fifo_alloc2\n    av_fifo_auto_grow_limit\n    av_fifo_can_read\n    av_fifo_can_write\n    av_fifo_drain\n    av_fifo_drain2\n    av_fifo_elem_size\n    av_fifo_free\n    av_fifo_freep\n    av_fifo_freep2\n    av_fifo_generic_peek\n    av_fifo_generic_peek_at\n    av_fifo_generic_read\n    av_fifo_generic_write\n    av_fifo_grow\n    av_fifo_grow2\n    av_fifo_peek\n    av_fifo_peek_to_cb\n    av_fifo_read\n    av_fifo_read_to_cb\n    av_fifo_realloc2\n    av_fifo_reset\n    av_fifo_reset2\n    av_fifo_size\n    av_fifo_space\n    av_fifo_write\n    av_fifo_write_from_cb\n    av_file_map\n    av_file_unmap\n    av_film_grain_params_alloc\n    av_film_grain_params_create_side_data\n    av_find_best_pix_fmt_of_2\n    av_find_info_tag\n    av_find_nearest_q_idx\n    av_fopen_utf8\n    av_force_cpu_flags\n    av_fourcc_make_string\n    av_frame_alloc\n    av_frame_apply_cropping\n    av_frame_clone\n    av_frame_copy\n    av_frame_copy_props\n    av_frame_free\n    av_frame_get_buffer\n    av_frame_get_plane_buffer\n    av_frame_get_side_data\n    av_frame_is_writable\n    av_frame_make_writable\n    av_frame_move_ref\n    av_frame_new_side_data\n    av_frame_new_side_data_from_buf\n    av_frame_ref\n    av_frame_remove_side_data\n    av_frame_side_data_name\n    av_frame_unref\n    av_free\n    av_freep\n    av_gcd\n    av_gcd_q\n    av_get_alt_sample_fmt\n    av_get_bits_per_pixel\n    av_get_bytes_per_sample\n    av_get_channel_description\n    av_get_channel_layout\n    av_get_channel_layout_channel_index\n    av_get_channel_layout_nb_channels\n    av_get_channel_layout_string\n    av_get_channel_name\n    av_get_colorspace_name\n    av_get_cpu_flags\n    av_get_default_channel_layout\n    av_get_extended_channel_layout\n    av_get_known_color_name\n    av_get_media_type_string\n    av_get_packed_sample_fmt\n    av_get_padded_bits_per_pixel\n    av_get_picture_type_char\n    av_get_pix_fmt\n    av_get_pix_fmt_loss\n    av_get_pix_fmt_name\n    av_get_pix_fmt_string\n    av_get_planar_sample_fmt\n    av_get_random_seed\n    av_get_sample_fmt\n    av_get_sample_fmt_name\n    av_get_sample_fmt_string\n    av_get_standard_channel_layout\n    av_get_time_base_q\n    av_get_token\n    av_gettime\n    av_gettime_relative\n    av_gettime_relative_is_monotonic\n    av_hash_alloc\n    av_hash_final\n    av_hash_final_b64\n    av_hash_final_bin\n    av_hash_final_hex\n    av_hash_freep\n    av_hash_get_name\n    av_hash_get_size\n    av_hash_init\n    av_hash_names\n    av_hash_update\n    av_hmac_alloc\n    av_hmac_calc\n    av_hmac_final\n    av_hmac_free\n    av_hmac_init\n    av_hmac_update\n    av_hwdevice_ctx_alloc\n    av_hwdevice_ctx_create\n    av_hwdevice_ctx_create_derived\n    av_hwdevice_ctx_create_derived_opts\n    av_hwdevice_ctx_init\n    av_hwdevice_find_type_by_name\n    av_hwdevice_get_hwframe_constraints\n    av_hwdevice_get_type_name\n    av_hwdevice_hwconfig_alloc\n    av_hwdevice_iterate_types\n    av_hwframe_constraints_free\n    av_hwframe_ctx_alloc\n    av_hwframe_ctx_create_derived\n    av_hwframe_ctx_init\n    av_hwframe_get_buffer\n    av_hwframe_map\n    av_hwframe_transfer_data\n    av_hwframe_transfer_get_formats\n    av_i2int\n    av_image_alloc\n    av_image_check_sar\n    av_image_check_size\n    av_image_check_size2\n    av_image_copy\n    av_image_copy_plane\n    av_image_copy_plane_uc_from\n    av_image_copy_to_buffer\n    av_image_copy_uc_from\n    av_image_fill_arrays\n    av_image_fill_black\n    av_image_fill_linesizes\n    av_image_fill_max_pixsteps\n    av_image_fill_plane_sizes\n    av_image_fill_pointers\n    av_image_get_buffer_size\n    av_image_get_linesize\n    av_int_list_length_for_size\n    av_int2i\n    av_lfg_init\n    av_lfg_init_from_data\n    av_log\n    av_log_default_callback\n    av_log_format_line\n    av_log_format_line2\n    av_log_get_flags\n    av_log_get_level\n    av_log_once\n    av_log_set_callback\n    av_log_set_flags\n    av_log_set_level\n    av_log2\n    av_log2_16bit\n    av_log2_i\n    av_lzo1x_decode\n    av_malloc\n    av_malloc_array\n    av_mallocz\n    av_mallocz_array\n    av_mastering_display_metadata_alloc\n    av_mastering_display_metadata_create_side_data\n    av_match_list\n    av_match_name\n    av_max_alloc\n    av_md5_alloc\n    av_md5_final\n    av_md5_init\n    av_md5_size\n    av_md5_sum\n    av_md5_update\n    av_memcpy_backptr\n    av_memdup\n    av_mod_i\n    av_mul_i\n    av_mul_q\n    av_murmur3_alloc\n    av_murmur3_final\n    av_murmur3_init\n    av_murmur3_init_seeded\n    av_murmur3_update\n    av_nearer_q\n    av_opt_child_class_iterate\n    av_opt_child_next\n    av_opt_copy\n    av_opt_eval_double\n    av_opt_eval_flags\n    av_opt_eval_float\n    av_opt_eval_int\n    av_opt_eval_int64\n    av_opt_eval_q\n    av_opt_find\n    av_opt_find2\n    av_opt_flag_is_set\n    av_opt_free\n    av_opt_freep_ranges\n    av_opt_get\n    av_opt_get_channel_layout\n    av_opt_get_chlayout\n    av_opt_get_dict_val\n    av_opt_get_double\n    av_opt_get_image_size\n    av_opt_get_int\n    av_opt_get_key_value\n    av_opt_get_pixel_fmt\n    av_opt_get_q\n    av_opt_get_sample_fmt\n    av_opt_get_video_rate\n    av_opt_is_set_to_default\n    av_opt_is_set_to_default_by_name\n    av_opt_next\n    av_opt_ptr\n    av_opt_query_ranges\n    av_opt_query_ranges_default\n    av_opt_serialize\n    av_opt_set\n    av_opt_set_bin\n    av_opt_set_channel_layout\n    av_opt_set_chlayout\n    av_opt_set_defaults\n    av_opt_set_defaults2\n    av_opt_set_dict\n    av_opt_set_dict_val\n    av_opt_set_dict2\n    av_opt_set_double\n    av_opt_set_from_string\n    av_opt_set_image_size\n    av_opt_set_int\n    av_opt_set_pixel_fmt\n    av_opt_set_q\n    av_opt_set_sample_fmt\n    av_opt_set_video_rate\n    av_opt_show2\n    av_parse_color\n    av_parse_cpu_caps\n    av_parse_ratio\n    av_parse_time\n    av_parse_video_rate\n    av_parse_video_size\n    av_pix_fmt_count_planes\n    av_pix_fmt_desc_get\n    av_pix_fmt_desc_get_id\n    av_pix_fmt_desc_next\n    av_pix_fmt_get_chroma_sub_sample\n    av_pix_fmt_swap_endianness\n    av_pixelutils_get_sad_fn\n    av_q2intfloat\n    av_rc4_alloc\n    av_rc4_crypt\n    av_rc4_init\n    av_read_image_line\n    av_read_image_line2\n    av_realloc\n    av_realloc_array\n    av_realloc_f\n    av_reallocp\n    av_reallocp_array\n    av_reduce\n    av_rescale\n    av_rescale_delta\n    av_rescale_q\n    av_rescale_q_rnd\n    av_rescale_rnd\n    av_ripemd_alloc\n    av_ripemd_final\n    av_ripemd_init\n    av_ripemd_size\n    av_ripemd_update\n    av_sample_fmt_is_planar\n    av_samples_alloc\n    av_samples_alloc_array_and_samples\n    av_samples_copy\n    av_samples_fill_arrays\n    av_samples_get_buffer_size\n    av_samples_set_silence\n    av_set_options_string\n    av_sha_alloc\n    av_sha_final\n    av_sha_init\n    av_sha_size\n    av_sha_update\n    av_sha512_alloc\n    av_sha512_final\n    av_sha512_init\n    av_sha512_size\n    av_sha512_update\n    av_shr_i\n    av_size_mult\n    av_small_strptime\n    av_spherical_alloc\n    av_spherical_from_name\n    av_spherical_projection_name\n    av_spherical_tile_bounds\n    av_sscanf\n    av_stereo3d_alloc\n    av_stereo3d_create_side_data\n    av_stereo3d_from_name\n    av_stereo3d_type_name\n    av_strcasecmp\n    av_strdup\n    av_strerror\n    av_strireplace\n    av_stristart\n    av_stristr\n    av_strlcat\n    av_strlcatf\n    av_strlcpy\n    av_strncasecmp\n    av_strndup\n    av_strnstr\n    av_strstart\n    av_strtod\n    av_strtok\n    av_sub_i\n    av_sub_q\n    av_tea_alloc\n    av_tea_crypt\n    av_tea_init\n    av_tea_size\n    av_tempfile\n    av_thread_message_flush\n    av_thread_message_queue_alloc\n    av_thread_message_queue_free\n    av_thread_message_queue_nb_elems\n    av_thread_message_queue_recv\n    av_thread_message_queue_send\n    av_thread_message_queue_set_err_recv\n    av_thread_message_queue_set_err_send\n    av_thread_message_queue_set_free_func\n    av_timecode_adjust_ntsc_framenum2\n    av_timecode_check_frame_rate\n    av_timecode_get_smpte\n    av_timecode_get_smpte_from_framenum\n    av_timecode_init\n    av_timecode_init_from_components\n    av_timecode_init_from_string\n    av_timecode_make_mpeg_tc_string\n    av_timecode_make_smpte_tc_string\n    av_timecode_make_smpte_tc_string2\n    av_timecode_make_string\n    av_timegm\n    av_tree_destroy\n    av_tree_enumerate\n    av_tree_find\n    av_tree_insert\n    av_tree_node_alloc\n    av_tree_node_size\n    av_twofish_alloc\n    av_twofish_crypt\n    av_twofish_init\n    av_twofish_size\n    av_tx_init\n    av_tx_uninit\n    av_usleep\n    av_utf8_decode\n    av_util_ffversion\n    av_uuid_parse\n    av_uuid_parse_range\n    av_uuid_unparse\n    av_uuid_urn_parse\n    av_vbprintf\n    av_version_info\n    av_video_enc_params_alloc\n    av_video_enc_params_create_side_data\n    av_vk_frame_alloc\n    av_vkfmt_from_pixfmt\n    av_vlog\n    av_write_image_line\n    av_write_image_line2\n    av_xtea_alloc\n    av_xtea_crypt\n    av_xtea_init\n    av_xtea_le_crypt\n    av_xtea_le_init\n    avpriv_alloc_fixed_dsp\n    avpriv_cga_font\n    avpriv_dict_set_timestamp\n    avpriv_float_dsp_alloc\n    avpriv_fopen_utf8\n    avpriv_get_gamma_from_trc\n    avpriv_get_trc_function_from_trc\n    avpriv_init_lls\n    avpriv_open\n    avpriv_report_missing_feature\n    avpriv_request_sample\n    avpriv_scalarproduct_float_c\n    avpriv_set_systematic_pal2\n    avpriv_slicethread_create\n    avpriv_slicethread_execute\n    avpriv_slicethread_free\n    avpriv_solve_lls\n    avpriv_tempfile\n    avpriv_vga16_font\n    avutil_configuration\n    avutil_license\n    avutil_version\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/lib/win/postproc-56.def",
    "content": "EXPORTS\n    postproc_configuration\n    postproc_ffversion\n    postproc_license\n    postproc_version\n    pp_free_context\n    pp_free_mode\n    pp_get_context\n    pp_get_mode_by_name_and_quality\n    pp_help\n    pp_postprocess\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/lib/win/swresample-4.def",
    "content": "EXPORTS\n    swr_alloc\n    swr_alloc_set_opts\n    swr_alloc_set_opts2\n    swr_build_matrix\n    swr_build_matrix2\n    swr_close\n    swr_config_frame\n    swr_convert\n    swr_convert_frame\n    swr_drop_output\n    swr_ffversion\n    swr_free\n    swr_get_class\n    swr_get_delay\n    swr_get_out_samples\n    swr_init\n    swr_inject_silence\n    swr_is_initialized\n    swr_next_pts\n    swr_set_channel_mapping\n    swr_set_compensation\n    swr_set_matrix\n    swresample_configuration\n    swresample_license\n    swresample_version\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/lib/win/swscale-6.def",
    "content": "EXPORTS\n    sws_alloc_context\n    sws_alloc_set_opts\n    sws_allocVec\n    sws_convertPalette8ToPacked24\n    sws_convertPalette8ToPacked32\n    sws_frame_end\n    sws_frame_start\n    sws_freeContext\n    sws_freeFilter\n    sws_freeVec\n    sws_get_class\n    sws_getCachedContext\n    sws_getCoefficients\n    sws_getColorspaceDetails\n    sws_getContext\n    sws_getDefaultFilter\n    sws_getGaussianVec\n    sws_init_context\n    sws_isSupportedEndiannessConversion\n    sws_isSupportedInput\n    sws_isSupportedOutput\n    sws_normalizeVec\n    sws_receive_slice\n    sws_receive_slice_alignment\n    sws_scale\n    sws_scale_frame\n    sws_scaleVec\n    sws_send_slice\n    sws_setColorspaceDetails\n    swscale_configuration\n    swscale_license\n    swscale_version\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/presets/libvpx-1080p.ffpreset",
    "content": "vcodec=libvpx\n\ng=120\nlag-in-frames=16\ndeadline=good\ncpu-used=0\nvprofile=1\nqmax=51\nqmin=11\nslices=4\nb=2M\n\n#ignored unless using -pass 2\nmaxrate=24M\nminrate=100k\nauto-alt-ref=1\narnr-maxframes=7\narnr-strength=5\narnr-type=centered\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/presets/libvpx-1080p50_60.ffpreset",
    "content": "vcodec=libvpx\n\ng=120\nlag-in-frames=25\ndeadline=good\ncpu-used=0\nvprofile=1\nqmax=51\nqmin=11\nslices=4\nb=2M\n\n#ignored unless using -pass 2\nmaxrate=24M\nminrate=100k\nauto-alt-ref=1\narnr-maxframes=7\narnr-strength=5\narnr-type=centered\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/presets/libvpx-360p.ffpreset",
    "content": "vcodec=libvpx\n\ng=120\nlag-in-frames=16\ndeadline=good\ncpu-used=0\nvprofile=0\nqmax=63\nqmin=0\nb=768k\n\n#ignored unless using -pass 2\nmaxrate=1.5M\nminrate=40k\nauto-alt-ref=1\narnr-maxframes=7\narnr-strength=5\narnr-type=centered\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/presets/libvpx-720p.ffpreset",
    "content": "vcodec=libvpx\n\ng=120\nlag-in-frames=16\ndeadline=good\ncpu-used=0\nvprofile=0\nqmax=51\nqmin=11\nslices=4\nb=2M\n\n#ignored unless using -pass 2\nmaxrate=24M\nminrate=100k\nauto-alt-ref=1\narnr-maxframes=7\narnr-strength=5\narnr-type=centered\n"
  },
  {
    "path": "wolf/third_party/ffmpeg/presets/libvpx-720p50_60.ffpreset",
    "content": "vcodec=libvpx\n\ng=120\nlag-in-frames=25\ndeadline=good\ncpu-used=0\nvprofile=0\nqmax=51\nqmin=11\nslices=4\nb=2M\n\n#ignored unless using -pass 2\nmaxrate=24M\nminrate=100k\nauto-alt-ref=1\narnr-maxframes=7\narnr-strength=5\narnr-type=centered\n"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/CMakeLists.txt",
    "content": "# <Copyright Holder>. Copyright (C) <Copyright Year(s)>. <License>.\n\n#\n# Project Properties\n#\ncmake_minimum_required (VERSION 3.18)\n\nif(NOT CMAKE_BUILD_TYPE)\n    set(CMAKE_BUILD_TYPE \"Debug\" CACHE STRING \"\" FORCE)\nendif()\n\nSTRING(TOLOWER \"${CMAKE_BUILD_TYPE}\" CMAKE_BUILD_TYPE_LOWER)\n\nPROJECT (dependencies)\nset (APPLICATION_NAME \"dependencies\")\nset (APPLICATION_CODENAME \"${PROJECT_NAME}\")\nset (APPLICATION_VERSION_MAJOR 1)\nset (APPLICATION_VERSION_MINOR 0)\nset (APPLICATION_VERSION_PATCH 0)\nset (APPLICATION_VERSION_TYPE SNAPSHOT)\nset (APPLICATION_VERSION_STRING \"${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}-${APPLICATION_VERSION_TYPE}\")\nset (APPLICATION_VENDOR_ID \"com.alpha\")\nset (APPLICATION_VENDOR_NAME \"ALPHA\")\nset (APPLICATION_VENDOR_URL \"alpha.com\")\nset (APPLICATION_ID \"${APPLICATION_VENDOR_ID}.${PROJECT_NAME}\")\n\nif(${CMAKE_BUILD_TYPE} MATCHES Debug)\n\tset (CMAKE_PROJECT_NAME ${PROJECT_NAME}d)\nelse()\n\tset (CMAKE_PROJECT_NAME ${PROJECT_NAME})\nendif()\n\nset(TARGET \"\" CACHE STRING \"target platform\")\n\ninclude(FetchContent)\n\nif(\"${TARGET}\" STREQUAL \"ANDROID\")\n    set(ANDROID TRUE)\nelseif(\"${TARGET}\" STREQUAL \"IOS\")\n    set(IOS TRUE)\nendif()\n\nif(CMAKE_SIZEOF_VOID_P EQUAL 8)\n    if (WIN32)\n        set(WIN64 TRUE)\n\t\tset(WIN32 FALSE)\n\t\tset(ANDROID FALSE)\n    endif()\nendif()\n\n# Note: Do not modify following properties\nif(WIN64)\n    set(ARCH \"x86_64\" CACHE STRING \"target architecture\")\n\tset(ARCH_S \"x64\")\n    set(TARGET_OS \"win64\")\n    set(PLATFORM \"win\")\nelseif(WIN32)\n    set(ARCH \"x86\" CACHE STRING \"target architecture\")\n    set(TARGET_OS \"win32\")\n    set(PLATFORM \"win\")\nelseif(ANDROID)\n    set(ARCH \"armv7-a\" CACHE STRING \"target architecture\")\n    set(TARGET_OS \"android\")\n    set(PLATFORM \"android\")\nelseif(IOS)\n    set(ARCH \"arm64\" CACHE STRING \"target architecture\")\n    set(TARGET_OS \"darwin\")\n    set(PLATFORM \"ios\")\nelseif(APPLE)\n    set(ARCH \"x86_64\" CACHE STRING \"target architecture\")\n    set(TARGET_OS \"darwin\")\n    set(PLATFORM \"osx\")\nendif()\n\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++11 \")\nSTRING(TOLOWER \"${CMAKE_BUILD_TYPE}\" CMAKE_BUILD_TYPE_LOWER)\n\noption(VP9_ENABLE \"Enable vp9 for ffmpeg\" OFF)\n\nif(IOS)\n     set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -arch ${ARCH}\")\n     set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -arch ${ARCH}\")\nendif()\n\nif(ANDROID)\n    if(NOT CMAKE_TOOLCHAIN_FILE)\n            message(FATAL_ERROR \"'CMAKE_TOOLCHAIN_FILE' variable is not set. Please set 'CMAKE_TOOLCHAIN_FILE' to the Android toolchain's path.\")\n    endif()\n    if(NOT NDK)\n            message(FATAL_ERROR \"'NDK' path is not specified. Please set 'NDK' to the Android NDK's path.\")\n    endif()\n\n    set(ANDROID_TOOLCHAIN_FILE CMAKE_TOOLCHAIN_FILE)\nendif()\n\n#\n# Debugging Options\n#\n# set (CMAKE_VERBOSE_MAKEFILE 0) # Use 1 for debugging, 0 for release\n\nif(WIN32 OR WIN64)\n\tset(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE} /MT\")\n\tset(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} /MTd\")\nendif()\n\n#\n# Project Output Paths\n#\nset (MAINFOLDER ${PROJECT_SOURCE_DIR})\n\nif(NOT EXECUTABLE_OUTPUT_PATH)\n    message(WARNING \"EXECUTABLE_OUTPUT_PATH has not been specified by the user. Use \\\"${MAINFOLDER}/bin/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\\\" as the default path.\")\n    set (EXECUTABLE_OUTPUT_PATH \"${MAINFOLDER}/bin/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\")\nendif()\nif(NOT LIBRARY_OUTPUT_PATH)\n    message(WARNING \"LIBRARY_OUTPUT_PATH has not been specified by the user. Use \\\"${MAINFOLDER}/lib/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\\\" as the default path.\")\n    set (LIBRARY_OUTPUT_PATH \"${MAINFOLDER}/lib/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\")\nendif()\n\n#\n# Project Search Paths\n#\nLIST (APPEND CMAKE_PREFIX_PATH \"${MAINFOLDER}\")\n\n#\n# DAV1D \n#\nset(DAV1D_LIBRARY \"${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}/src\")\nset(DAV1D_INCLUDES \"${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}/include/dav1d\")\nset(DAV1D_SOURCES \"${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-src/include\")\n\n#\n# SVT-AV1\n#\nset(SVTAV1_LIBRARY \"${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-src/Bin/${CMAKE_BUILD_TYPE}\")\nset(SVTAV1_INCLUDES \"${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-src/Source/API\")\n\n#\n# VP9\n#\nif(VP9_ENABLE)\n\tset(VP9_OPTION \"--enable-libvpx\")\n\tset(VP9_INCLUDES \"${CMAKE_BINARY_DIR}/third_party/vpx/vpx-src\")\n\tif(APPLE)\n\t\tset(VP9_LIBRARY \"${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\")\n\telse()\n\t\tset(VP9_LIBRARY \"${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH_S}/${CMAKE_BUILD_TYPE}\")\n\tendif()\nendif()\n\n#\n# FFMPEG\n#\nset (FFMPEGFOLDER \"${MAINFOLDER}/FFMPEG/ffmpeg-src\")\nINCLUDE_DIRECTORIES(\"${FFMPEGFOLDER}\")\n\n#\n# Configure Files\n#\n\nFILE (GLOB_RECURSE CONFIGINPUTS1 FFMPEG/*.in.h.cmake)\nFILE (GLOB_RECURSE CONFIGINPUTS2 FFMPEG/*.h.in.cmake)\nFILE (GLOB_RECURSE CONFIGINPUTS3 third_party/dav1d/*.in.h.cmake)\nFILE (GLOB_RECURSE CONFIGINPUTS4 third_party/svt-av1/*.in.h.cmake)\nif(VP9_ENABLE)\n\tFILE (GLOB_RECURSE CONFIGINPUTS5 third_party/vpx/*.in.h.cmake)\nendif()\nLIST (APPEND CONFIGINPUTS \"${CONFIGINPUTS1}\")\nLIST (APPEND CONFIGINPUTS \"${CONFIGINPUTS2}\")\nLIST (APPEND CONFIGINPUTS \"${CONFIGINPUTS3}\")\nLIST (APPEND CONFIGINPUTS \"${CONFIGINPUTS4}\")\nif(VP9_ENABLE)\n\tLIST (APPEND CONFIGINPUTS \"${CONFIGINPUTS5}\")\nendif()\n\nFOREACH (CONFIGINPUT ${CONFIGINPUTS})\n    STRING (REPLACE \".in.h.cmake\" \".h\" CONFIGOUTPUT1 \"${CONFIGINPUT}\")\n    STRING (REPLACE \".h.in.cmake\" \".h\" CONFIGOUTPUT2 \"${CONFIGOUTPUT1}\")\n    CONFIGURE_FILE (\"${CONFIGINPUT}\" \"${CONFIGOUTPUT2}\" \"${CONFIGOUTPUT2}\")\nENDFOREACH (CONFIGINPUT ${CONFIGINPUTS})\n\n#\n# Add Build Targets\n#\nADD_SUBDIRECTORY(third_party/dav1d)\nADD_SUBDIRECTORY(third_party/svt-av1)\nif(VP9_ENABLE)\n\tADD_SUBDIRECTORY(third_party/vpx)\nendif()\nADD_SUBDIRECTORY(FFMPEG)\n\n"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/FFMPEG/CMakeLists-FFMPEG.txt.in",
    "content": "cmake_minimum_required(VERSION 2.8.2)\n\nproject(ffmpeg-download NONE)\n\ninclude(ExternalProject)\nExternalProject_Add(FFMPEG\n  GIT_REPOSITORY    https://github.com/FFmpeg/FFmpeg.git\n  GIT_TAG           master\n  SOURCE_DIR        \"${MAINFOLDER}/FFMPEG/ffmpeg-src\"\n  BINARY_DIR        \"${MAINFOLDER}/FFMPEG/ffmpeg-build\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND     \"\"\n  INSTALL_COMMAND   \"\"\n  TEST_COMMAND      \"\"\n)"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/FFMPEG/CMakeLists.txt",
    "content": "#\n# FFMPEG\n#\n#cmake_policy(set CMP0040 OLD)\n\nif(IOS)\n    set(DEPLOYMENT_TARGET 11.0)\n    execute_process(COMMAND sh -c \"xcode-select -print-path\" OUTPUT_VARIABLE XCODE_ROOT OUTPUT_STRIP_TRAILING_WHITESPACE)\n    set(DEVROOT \"${XCODE_ROOT}/Platforms/iPhoneOS.platform/Developer\")\n    set(SDKROOT \"${DEVROOT}/SDKs/iPhoneOS.sdk\")\n    set(CFLAGS \"-arch ${ARCH}\")\n    set(CFLAGS \"${CFLAGS}  -isysroot ${SDKROOT} -mios-version-min=${DEPLOYMENT_TARGET}\")\nelseif(ANDROID)\n    set(BASEDIR $(pwd))\n#    set(NDK /home/siminbadri/Documents/android-ndk-r23)\n    set(TOOLCHAIN ${NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin)\n    set(SYSROOT ${NDK}/toolchains/llvm/prebuilt/linux-x86_64/sysroot)\n    set(CFLAGS \"-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all -lssp -fpie\n        -I${TOOLCHAIN}/../include/c++/4.9.x/\")\nendif()\n\nif(${CMAKE_BUILD_TYPE} MATCHES Debug)\n    set(CONFIGURE_FLAGS \"--enable-debug\")\n    if(NOT IOS AND NOT APPLE)\n        set(CONFIGURE_FLAGS \"${CONFIGURE_FLAGS} --extra-cflags=-MDd --extra-ldflags=/NODEFAULTLIB:libcmt\")\n    endif()\nendif()\n\nconfigure_file(CMakeLists-FFMPEG.txt.in\n               FFMPEG-download/CMakeLists.txt)\nexecute_process(COMMAND ${CMAKE_COMMAND} -G \"${CMAKE_GENERATOR}\" -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE\n\t\t\t\t.\n\t\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/FFMPEG-download )\nexecute_process(COMMAND ${CMAKE_COMMAND} --build .\n\t\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/FFMPEG-download )\n\nif(IOS)\n    execute_process(COMMAND sh -c \"\\\n                 ./configure \\\n                 --enable-asm --enable-yasm \\\n                 --disable-doc --disable-ffplay \\\n                 --disable-ffprobe --disable-ffmpeg --enable-shared --disable-static --disable-bzlib \\\n                 --disable-libopenjpeg --disable-iconv --disable-zlib --disable-audiotoolbox --enable-cross-compile \\\n                 --prefix=${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE} \\\n                 --cc=${XCODE_ROOT}/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang \\\n                 --cxx=${XCODE_ROOT}/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ --extra-cflags=\\\"${CFLAGS}\\\" \\\n                 --extra-ldflags=\\\"${CFLAGS}\\\"\\\n                 --target-os=${TARGET_OS} --arch=${ARCH} ${CONFIGURE_FLAGS} && make clean && make && make install\"\n                 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src)\nelseif(APPLE)\n    add_custom_command(OUTPUT ffmpeg_command\n        COMMAND  export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-src/Build/linux/${CMAKE_BUILD_TYPE}:${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}/meson-private:${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE} && \n\t\t ./configure\n                 --enable-asm --enable-yasm\n                 --enable-libdav1d --enable-libsvtav1\n                 --extra-ldflags=-L${SVTAV1_LIBRARY}\n                 --extra-ldflags=-L${DAV1D_LIBRARY}\n                 --extra-ldflags=-L${VP9_LIBRARY}\n                 --extra-cflags=-I${SVTAV1_INCLUDES}\n                 --extra-cflags=-I${DAV1D_SOURCES}\n                 --extra-cflags=-I${DAV1D_INCLUDES}\n                 --extra-cflags=-I${VP9_INCLUDES}\n                 --disable-doc --enable-ffplay ${VP9_OPTION}\n                 --disable-ffprobe --enable-ffmpeg --enable-shared --enable-static --disable-bzlib\n                     --disable-libopenjpeg --disable-iconv\n                 --prefix=${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\n                 --target-os=${TARGET_OS} --arch=${ARCH} ${CONFIGURE_FLAGS} && make clean && make && make install\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src\n        COMMENT \"Building FFMPEG\")\n    \n    add_custom_target(ffmpeg ALL\n        DEPENDS ffmpeg_command\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src\n        VERBATIM)\nelseif(WIN32 OR WIN64)\n    string(REGEX REPLACE \":\" \"\" MSYS_CMAKE_BINARY_DIR \"${CMAKE_BINARY_DIR}\")\n    add_custom_command(OUTPUT ffmpeg_command\n        \t\tCOMMAND cmd.exe /C \"msys2_shell.cmd -use-full-path -no-start -here -mingw64 -c \\\" \\\n\t\t\texport PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/${MSYS_CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}/meson-private:/${MSYS_CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-src/Build/windows/ && \\\n\t\t\t./configure \\\n\t\t\t--disable-x86asm --enable-libdav1d --enable-libsvtav1\\\n\t\t\t--extra-ldflags=\\\"-LIBPATH:${SVTAV1_LIBRARY}\\\" \\\n\t\t\t--extra-ldflags=\\\"-LIBPATH:${DAV1D_LIBRARY}\\\" \\\n            --extra-ldflags=\\\"-LIBPATH:${VP9_LIBRARY}\\\" \\\n            --extra-ldflags=\\\"-LIBPATH:${VP9_LIBRARY}\\\" \\\n\t\t\t--extra-cflags=\\\"-I${SVTAV1_INCLUDES}\\\" \\\n\t\t\t--extra-cflags=\\\"-I${DAV1D_SOURCES}\\\" \\\n\t\t\t--extra-cflags=\\\"-I${DAV1D_INCLUDES}\\\" \\\n            --extra-cflags=\\\"-I${VP9_INCLUDES}\\\" \\\n\t\t\t--extra-cflags=\\\"-MTd\\\" \\\n\t\t\t--extra-ldflags=\\\"/NODEFAULTLIB:library\\\" \\\n\t\t\t--disable-doc --enable-ffplay ${VP9_OPTION} \\\n\t\t\t--disable-ffprobe --enable-ffmpeg --enable-shared --enable-static --disable-bzlib \\\n\t\t\t--disable-libopenjpeg --disable-iconv --disable-zlib\\\n\t\t\t--prefix=${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE} \\\n\t\t\t--target-os=${TARGET_OS} --arch=${ARCH} --toolchain=msvc ${CONFIGURE_FLAGS} && make clean && make && make install\\\"\"\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src\n        COMMENT \"Building FFMPEG\")\n    \n\tif(VP9_ENABLE)\n\t\tadd_custom_target(ffmpeg ALL\n\t\t\tDEPENDS ffmpeg_command\n\t\t\tDEPENDS dav1d\n\t\t\tDEPENDS svt1v1\n\t\t\tDEPENDS vpx\n\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src\n\t\t\tVERBATIM)\n\telse()\n\t\tadd_custom_target(ffmpeg ALL\n\t\t\tDEPENDS ffmpeg_command\n\t\t\tDEPENDS dav1d\n\t\t\tDEPENDS svt1v1\n\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src\n\t\t\tVERBATIM)\n\tendif()\n\nelseif(ANDROID)\n    execute_process(COMMAND sh \"-c\" \"./configure \\\n\t\t\t\t --disable-asm \\\n\t\t\t\t --disable-doc --disable-ffplay \\\n\t\t\t\t --disable-ffprobe --disable-ffmpeg --enable-shared --disable-static --disable-bzlib \\\n\t\t\t\t --disable-libopenjpeg --disable-iconv --disable-zlib \\\n\t\t\t\t --prefix=${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE} \\\n\t\t\t\t --target-os=${TARGET_OS} --arch=${ARCH} ${CONFIGURE_FLAGS} \\\n\t\t\t\t --cpu=${ARCH} --cc=${TOOLCHAIN}/armv7a-linux-androideabi19-clang \\\n\t\t\t\t --cxx=${TOOLCHAIN}/armv7a-linux-androideabi19-clang++ \\\n\t\t\t\t --nm=${TOOLCHAIN}/llvm-nm --ar=${TOOLCHAIN}/llvm-ar \\\n\t\t\t\t --ranlib=${TOOLCHAIN}/llvm-ranlib --strip=${TOOLCHAIN}/llvm-strip \\\n\t\t\t\t --ld=${TOOLCHAIN}/ld --enable-pic --enable-cross-compile \\\n\t\t\t\t --extra-cflags=\"${CFLAGS}\" \\\n\t\t\t\t --extra-ldflags=\\\"-Wl,soname=$(SLIBNAME) -z notext $LDFLAGS -L${SYSROOT}/usr/lib/arm-linux-androideabi/19\\\"\"\n\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src)\n\n# Modify FFMPEG generated Makefile\nexecute_process(COMMAND sed -i -e \"s/HAVE_CBRT 0/HAVE_CBRT 1/g; \\\n\t\t\t\t   s/HAVE_CBRTF 0/HAVE_CBRTF 1/g; \\\n\t\t\t\t   s/HAVE_COPYSIGN 0/HAVE_COPYSIGN 1/g; \\\n\t\t\t\t   s/HAVE_ERF 0/HAVE_ERF 1/g; \\\n\t\t\t\t   s/HAVE_HYPOT 0/HAVE_HYPOT 1/g; \\\n\t\t\t\t   s/HAVE_INET_ATON 0/HAVE_INET_ATON 1/g; \\\n\t\t\t\t   /#define getenv(x) NULL/d; \\\n\t\t\t\t   s/HAVE_ISINF 0/HAVE_ISINF 1/g; \\\n\t\t\t\t   s/HAVE_ISNAN 0/HAVE_ISNAN 1/g; \\\n\t\t\t\t   s/HAVE_RINT 0/HAVE_RINT 1/g; \\\n\t\t\t\t   s/HAVE_LRINT 0/HAVE_LRINT 1/g; \\\n\t\t\t\t   s/HAVE_LRINTF 0/HAVE_LRINTF 1/g; \\\n\t\t\t\t   s/HAVE_ROUND 0/HAVE_ROUND 1/g; \\\n\t\t\t\t   s/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g; \\\n\t\t\t\t   s/HAVE_TRUNC 0/HAVE_TRUNC 1/g; \\\n\t\t\t\t   s/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g\" ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src/config.h)\n\n# Modify config.mak\nexecute_process(COMMAND sed -i -e \"s/SHFLAGS=-shared -Wl,-soname,$(SLIBNAME)/SHFLAGS=-shared -soname $(SLIBNAME)/g\"\n\t\t\t${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src/ffbuild/config.mak)\n\nexecute_process(COMMAND bash \"-c\" \"make clean && make && make install\" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/FFMPEG/ffmpeg-src)\nendif()\n"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/third_party/dav1d/CMakeLists-dav1d.txt.in",
    "content": "cmake_minimum_required(VERSION 2.8.2)\n\nproject(dav1d-download NONE)\n\ninclude(ExternalProject)\nExternalProject_Add(dav1d\n  GIT_REPOSITORY    https://code.videolan.org/videolan/dav1d.git\n  GIT_TAG           master\n  SOURCE_DIR        \"${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-src\"\n  BINARY_DIR        \"${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND     \"\"\n  INSTALL_COMMAND   \"\"\n  TEST_COMMAND      \"\"\n)"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/third_party/dav1d/CMakeLists.txt",
    "content": "#\n# DAV1D\n#\n#cmake_policy(set CMP0040 OLD)\n\nconfigure_file(CMakeLists-dav1d.txt.in\n               dav1d-download/CMakeLists.txt)\n\t\t\t   \nexecute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE})\n\t\t\t   \nexecute_process(COMMAND ${CMAKE_COMMAND} -G \"${CMAKE_GENERATOR}\" -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\n\t\t\t\t.\n\t\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-download )\nexecute_process(COMMAND ${CMAKE_COMMAND} --build .\n\t\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-download )\n  \nif(WIN32 OR WIN64)\n\texecute_process(COMMAND cmd.exe /c \"msys2_shell.cmd -defterm -use-full-path -no-start -here -mingw64 -c \\\" \\\n\t\tyes | pacman -S mingw-w64-x86_64-nasm \\\"\")\n\n    add_custom_command(OUTPUT dav1d_command\n        COMMAND meson setup ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE} --buildtype ${CMAKE_BUILD_TYPE_LOWER} && cd ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE} && ninja\n        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}/include/dav1d/version.h\n\t\t${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-src/include/dav1d/\n\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-src/\n        COMMENT \"Building DAV1D\")\nelseif(APPLE)\n    add_custom_command(OUTPUT dav1d_command\n        COMMAND meson setup ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE} --buildtype ${CMAKE_BUILD_TYPE_LOWER} && cd ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE} && ninja\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-src/\n        COMMENT \"Building DAV1D\")\nendif()\n\nadd_custom_target(dav1d ALL\n    DEPENDS dav1d_command\n    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/dav1d/dav1d-src/\n    VERBATIM)\n"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/third_party/svt-av1/CMakeLists-svtav1.txt.in",
    "content": "cmake_minimum_required(VERSION 2.8.2)\n\nproject(svtav1-download NONE)\n\ninclude(ExternalProject)\nExternalProject_Add(svtav1\n  GIT_REPOSITORY    https://github.com/AOMediaCodec/SVT-AV1.git\n  GIT_TAG           master\n  SOURCE_DIR        \"${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-src\"\n  BINARY_DIR        \"${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-build\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND     \"\"\n  INSTALL_COMMAND   \"\"\n  TEST_COMMAND      \"\"\n)"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/third_party/svt-av1/CMakeLists.txt",
    "content": "#\n# SVT-AV1\n#\n#cmake_policy(set CMP0040 OLD)\n\nconfigure_file(CMakeLists-svtav1.txt.in\n               svtav1-download/CMakeLists.txt)\n\t\t\t   \t\t\t   \nexecute_process(COMMAND ${CMAKE_COMMAND} -G \"${CMAKE_GENERATOR}\" -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\n\t\t\t\t.\n\t\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-download )\nexecute_process(COMMAND ${CMAKE_COMMAND} --build .\n\t\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-download )\n\nif(WIN32 OR WIN64)\n    add_custom_command(OUTPUT svt1v1_command\n        COMMAND build.bat 2022 ${CMAKE_BUILD_TYPE}\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-src/Build/windows\n        COMMENT \"Building SVTAV1\")\nelseif(APPLE)\n    add_custom_command(OUTPUT svt1v1_command\n        COMMAND ./build.sh ${CMAKE_BUILD_TYPE}\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-src/Build/linux\n        COMMENT \"Building SVTAV1\")\nendif()\n\nadd_custom_target(svt1v1 ALL\n    DEPENDS svt1v1_command\n    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/svt-av1/svtav1-src\n    VERBATIM)\n"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/third_party/vpx/CMakeLists-vpx.txt.in",
    "content": "cmake_minimum_required(VERSION 2.8.2)\n\nproject(vpx-download NONE)\n\ninclude(ExternalProject)\nExternalProject_Add(vpx\n  GIT_REPOSITORY    https://chromium.googlesource.com/webm/libvpx\n  GIT_TAG           main\n  SOURCE_DIR        \"${CMAKE_BINARY_DIR}/third_party/vpx/vpx-src\"\n  BINARY_DIR        \"${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build\"\n  CONFIGURE_COMMAND \"\"\n  BUILD_COMMAND     \"\"\n  INSTALL_COMMAND   \"\"\n  TEST_COMMAND      \"\"\n)"
  },
  {
    "path": "wolf/third_party/shells/ffmpeg/third_party/vpx/CMakeLists.txt",
    "content": "#\n# VPX\n#\n#cmake_policy(set CMP0040 OLD)\n\nconfigure_file(CMakeLists-vpx.txt.in\n               vpx-download/CMakeLists.txt)\n\t\t\t   \t\t\t   \nexecute_process(COMMAND ${CMAKE_COMMAND} -G \"${CMAKE_GENERATOR}\" -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\n\t\t\t\t.\n\t\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-download )\nexecute_process(COMMAND ${CMAKE_COMMAND} --build .\n\t\t\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-download )\n  \nexecute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE})\n\nif(WIN64)\n\tset(CONFIGURE_FLAGS \"--target=x86_64-win64-vs17 --enable-static-msvcrt\")\nelseif(WIN32)\n\tset(CONFIGURE_FLAGS \"--target=x86-win32-vs17 --enable-static-msvcrt\")\nendif()\n\nif(${CMAKE_BUILD_TYPE} MATCHES Debug)\n\tset(VPX_LIB_NAME \"vpxmtd.lib\")\nelse()\n\tset(VPX_LIB_NAME \"vpxmt.lib\")\nendif()\n\nif(WIN64 OR WIN32)\n    add_custom_command(OUTPUT vpx_command\n\t\tCOMMAND cmd.exe /c \"msys2_shell.cmd -use-full-path -no-start -here -mingw64 -c \\\" \\\n\t\tyes | pacman -S mingw-w64-x86_64-nasm\\\n\t\t&& ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-src/configure ${CONFIGURE_FLAGS} \\\n        && make \\\"\"\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/\n        COMMENT \"Building LIBVPX\")\n    add_custom_command(OUTPUT vpx_rename_command\n\t\tCOMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH_S}/${CMAKE_BUILD_TYPE}/${VPX_LIB_NAME} \n\t\t${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH_S}/${CMAKE_BUILD_TYPE}/vpx.lib\n\t\tDEPENDS vpx_command\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\n        COMMENT \"Building LIBVPX\")\n\t\t\n\tadd_custom_target(vpx ALL\n\t\tDEPENDS vpx_command\n\t\tDEPENDS vpx_rename_command\n\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\n\t\tVERBATIM)\nelseif(APPLE)\n    add_custom_command(OUTPUT vpx_command\n        COMMAND ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-src/configure\n        COMMAND make\n        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\n        COMMENT \"Building LIBVPX\")\n\t\t\n\tadd_custom_target(vpx ALL\n\t\tDEPENDS vpx_command\n\t\tWORKING_DIRECTORY ${CMAKE_BINARY_DIR}/third_party/vpx/vpx-build/${PLATFORM}/${ARCH}/${CMAKE_BUILD_TYPE}\n\t\tVERBATIM)\nendif()\n"
  },
  {
    "path": "wolf/third_party/shells/janus/setup.sh",
    "content": "#!/bin/bash\n# any case there is an issue, check this \"https://github.com/meetecho/janus-gateway\"\n\necho \"setup the prerequisites\"\nsudo apt-get install meson libmicrohttpd-dev libjansson-dev libssl-dev libsrtp2-dev libsofia-sip-ua-dev libglib2.0-dev libopus-dev libogg-dev libcurl4-openssl-dev liblua5.3-dev libconfig-dev pkg-config libtool automake\necho \"installing libnice\"\ngit clone https://gitlab.freedesktop.org/libnice/libnice\ncd libnice\nmeson --prefix=/usr build && ninja -C build && sudo ninja -C build install\ncd ..\nwget https://github.com/cisco/libsrtp/archive/v2.2.0.tar.gz\ntar xfv v2.2.0.tar.gz\ncd libsrtp-2.2.0\n./configure --prefix=/usr --enable-openssl\nmake shared_library && sudo make install\necho \"installing boringssl\"\ncd ..\ngit clone https://boringssl.googlesource.com/boringssl\ncd boringssl\n# don't barf on errors\nsed -i s/\" -Werror\"//g CMakeLists.txt\nmkdir -p build\ncd build\ncmake -DCMAKE_CXX_FLAGS=\"-lrt\" ..\nmake\ncd ..\nsudo mkdir -p /opt/boringssl\nsudo cp -R include /opt/boringssl/\nsudo mkdir -p /opt/boringssl/lib\nsudo cp build/ssl/libssl.a /opt/boringssl/lib/\nsudo cp build/crypto/libcrypto.a /opt/boringssl/lib/\necho \"installing usrsctp\"\ncd ..\ngit clone https://github.com/sctplab/usrsctp\ncd usrsctp\n./bootstrap\n./configure --prefix=/usr --disable-programs --disable-inet --disable-inet6\nmake && sudo make install\necho \"installing nanomsg\"\ncd ..\naptitude install libnanomsg-dev\nsh autogen.sh\n./configure --prefix=/usr/local/janus PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig --enable-nanomsg --enable-data-channels\nsudo make install\nsudo make configs\necho \"all done.\"\necho \"you can change the config of \\'janus.transport.http.jcfg\\' from \\'/usr/local/janus/etc/janus/janus.transport.http.jcfg\\' and change the following \\n\n\\n\ngeneral: {\n\thttps = true\t\t\t\t\t# Whether to enable HTTPS \n\tsecure_port = 8089\t\t\t\t# Web server HTTPS port, if enabled\n}\n\\n\ncertificates: {\n\tcert_pem = \"/path/to/the/cert.pem\"\n\tcert_key = \"/path/to/the/cert.key\"\n}\n\\n\"\necho \"running Janus\"\ncd /usr/local/janus/bin \nsudo janus"
  },
  {
    "path": "wolf/third_party/shells/librist/android-arm.ini",
    "content": "[binaries]\nc       = 'armv7a-linux-androideabi24-clang'\ncpp     = 'armv7a-linux-androideabi24-clang++'\nar      = 'arm-linux-androideabi-ar'\nas      = 'arm-linux-androideabi-as'\nranlib  = 'arm-linux-androideabi-ranlib'\nld      = 'arm-linux-androideabi-ld'\nstrip   = 'arm-linux-androideabi-strip'\npkgconfig = 'false'\n\n# XXX template sysroot\n[properties]\nc_args = '-fPIE -fPIC --target=armv7-none-linux-androideabi'\nc_link_args = ''\n\ncpp_args = '-fPIE -fPIC --target=armv7-none-linux-androideabi'\ncpp_link_args = ''\n\n"
  },
  {
    "path": "wolf/third_party/shells/librist/android-armv8.ini",
    "content": "[binaries]\nc       = 'aarch64-linux-android24-clang'\ncpp     = 'aarch64-linux-android24-clang++'\nar      = 'aarch64-linux-android-ar'\nas      = 'aarch64-linux-android-as'\nranlib  = 'aarch64-linux-android-ranlib'\nld      = 'aarch64-linux-android-ld'\nstrip   = 'aarch64-linux-android-strip'\npkgconfig = 'false'\n\n# XXX template sysroot\n[properties]\nc_args = '-arch aarch64 -fPIE -fPIC --target=aarch64-none-linux-android'\nc_link_args = ''\n\ncpp_args = '-arch aarch64 -fPIE -fPIC --target=aarch64-none-linux-android'\ncpp_link_args = ''\n\n[host_machine]\nsystem = 'darwin'\ncpu_family = 'aarch64'\ncpu = 'armv8-a'\nendian = 'little'\n"
  },
  {
    "path": "wolf/third_party/shells/librist/librist-android.sh",
    "content": "#!/bin/bash\n\nwhile [ \"$1\" != \"\" ]; do\n    case $1 in\n        --build_dir=* )             BUILD_DIR=\"${1#*=}\"\n                                    ;;\n        esac\n        shift\ndone\n\nTOOLCHAIN=\"${NDK}/build/cmake/android.toolchain.cmake\"\n\nHOST_ROOT=\"${NDK}/toolchains/llvm/prebuilt/darwin-x86_64\"\nSYS_ROOT=\"${HOST_ROOT}/sysroot\"\nLIB_PATH=\"${HOST_ROOT}/lib64:${SYS_ROOT}/usr/lib/${ARCH}-linux-androideabi:${SYS_ROOT}/usr/lib/${ARCH}-linux-androideabi/${ANDROID_NATIVE_API_LEVEL}\"\nINC_PATH=\"${SYS_ROOT}/usr/include\"\n\nexport PATH=\"${HOST_ROOT}/bin:${PATH}\"\nexport CMAKE_PREFIX_PATH=\"${SYS_ROOT}\"\nexport CMAKE_LIBRARY_PATH=${LIB_PATH}\nexport CMAKE_INCLUDE_PATH=${INC_PATH}\n\nexport CFLAGS=\"-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN} \\\n  -DANDROID_STL=c++_shared \\\n  -DANDROID_TOOLCHAIN=clang \\\n  -DANDROID_PLATFORM=android-${ANDROID_NATIVE_API_LEVEL} \\\n  -DANDROID_ABI=${ANDROID_ABI}\"\n\nrm -rf ${BUILD_DIR}\n\nDIR=\"$( dirname -- \"$0\"; )\";\n\nmeson configure -Dbuiltin_mbedtls=true\n\nmeson setup --errorlogs  \\\n  --prefix=${NDK} \\\n  --includedir=${INC_PATH} \\\n  --libdir=${LIB_PATH} \\\n  --build.cmake-prefix-path=${SYS_ROOT} \\\n  --cross-file ${DIR}/android-${CPU}.ini  \\\n  --default-library=static \\\n  ${BUILD_DIR} .\n\nninja -C ${BUILD_DIR}\n"
  },
  {
    "path": "wolf/third_party/shells/librist/librist.bat",
    "content": "if not exist \"librist/\" (\n    echo fetching rist\n    git clone --recursive https://code.videolan.org/rist/librist.git\n)\ncd librist\nmeson setup build --backend vs2022 --default-library static --buildtype %1\nmeson compile -C build"
  },
  {
    "path": "wolf/third_party/shells/librist/librist.sh",
    "content": "#!/bin/bash\n\nif ! [ -d \"/librist\" ]\nthen\n    echo fetching rist\n    git clone --recursive https://code.videolan.org/rist/librist.git\nfi\ncd librist\nmeson setup build --default-library static --buildtype $1\ncd build\nninja"
  },
  {
    "path": "wolf/third_party/shells/webRTC/webRTC.bat",
    "content": "echo \"check all args\"\ngn args out\\Debug --list --short\necho \"check overrided args\"\ngn args out\\Debug --list --short --overrides-only\necho \"set DEPOT_TOOLS_WIN_TOOLCHAIN=0 and set GYP_MSVS_VERSION=2022 to the environment  variables\"\necho \"build for debug\"\ngn gen out\\Debug --args=\"target_os=\\\"win\\\" target_cpu=\\\"x64\\\" is_debug=true use_lld=false is_clang=true use_rtti=true is_component_build=false treat_warnings_as_errors=false rtc_include_tests=false rtc_build_tools=false rtc_build_examples=false enable_libaom=true rtc_enable_protobuf=false rtc_libvpx_build_vp9=true ffmpeg_branding=\\\"Chrome\\\" rtc_use_h264=true proprietary_codecs=true use_custom_libcxx=true\"\necho \"build for release\"\ngn gen out\\Debug --args=\"is_debug=false\"\necho \"build\"\nninja -C out\\Debug\n"
  },
  {
    "path": "wolf/third_party/shells/webRTC/webRTC.sh",
    "content": "#!/bin/bash\n\n# first setup depth_tools https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up\n\ngit clone https://chromium.googlesource.com/chromium/tools/depot_tools.git\nexport PATH=$PWD/depot_tools:$PATH\n\n# now get webrtc-checkout\nmkdir webrtc-checkout\ncd webrtc-checkout\nfetch --nohooks webrtc\ngclient sync\ncd src\n\nbuild_type=debug\nis_debug = true\nif [ $2 = \"release\" ]; then\n    build_type=release\n    is_debug = false\nfi\n\nif [ $1 = \"ios\" ]; then\n    # Compile version without certificate\n    gn gen out/ios_$build_type --args='target_os=\"ios\" target_cpu=\"arm64\" is_debug=$is_debug use_rtti=true is_component_build=false ios_enable_code_signing=false proprietary_codecs=false rtc_include_tests=false' --ide=xcode\n    ninja -C out/ios_$build_type\n\n    # Compile version with certificate\n\n    # Get the certificate name\n    # security find-identity -v -p codesigning\n\n    # # Compile with the above key\n    # gn gen out/ios_$build_type_sign --args='target_os=\"ios\" target_cpu=\"arm64\" is_debug=$is_debug use_rtti=true is_component_build=false ios_code_signing_identity=\"The string of numbers obtained by the above command\" proprietary_codecs=false rtc_use_h264= false rtc_include_tests=false' --ide=xcode\n    # ninja -C out/ios_$build_type_sign\nelse\n    # mac & linux\n    gn gen out/$build_type --args='target_os=\"$1\" target_cpu=\"x64\" is_debug=$is_debug use_rtti=true is_component_build=false rtc_include_tests=false use_custom_libcxx=false use_custom_libcxx_for_host=false' --ide=xcode\n    ninja -C out/$build_type\nfi\n\n\n"
  },
  {
    "path": "wolf/wolf.cpp",
    "content": "﻿#include \"wolf.hpp\"\n\n#ifdef WOLF_SYSTEM_MIMALLOC\n\n#include <mimalloc-new-delete.h>\n#include <mimalloc-override.h>\n\n#endif\n\n#ifdef WOLF_SYSTEM_STACKTRACE\n\n#include <csignal>\n#include <filesystem>\n#include <fstream>\n#include <sstream>\n#include <stacktrace>\n#include <system/w_process.hpp>\n\nstatic void w_signal_handler(int p_signum) {\n  auto _path = wolf::system::w_process::current_exe_path();\n  if (_path.has_error()) {\n    return;\n  }\n\n  const auto &_path_str = _path.value().append(\"wolf.dump\");\n\n  std::ignore = signal(p_signum, nullptr);\n\n  std::stringstream _traces;\n\n#ifdef __clang__\n#pragma unroll\n#endif  // __clang__\n  for (const auto &trace : std::stacktrace()) {\n    _traces << \"name: \" << trace.description()\n            << \" source_file: \" << trace.source_file() << \"(\"\n            << std::to_string(trace.source_line()) << \")\\r\\n\";\n  }\n\n  std::fstream _file;\n  _file.open(_path_str.string(), std::ios_base::out);\n  if (_file.is_open()) {\n    _file << _traces.str();\n    _file.close();\n  }\n\n  std::ignore = raise(SIGABRT);\n}\n\n#endif\n\nstd::string wolf::w_init() {\n#if defined(WOLF_SYSTEM_STACKTRACE) && !defined(WOLF_TESTS)\n  std::ignore = signal(SIGSEGV, &w_signal_handler);\n  std::ignore = signal(SIGABRT, &w_signal_handler);\n#endif\n\n  // Making incompatible API changes\n  constexpr auto WOLF_MAJOR_VERSION = 3;\n  // Adding functionality in a backwards - compatible manner\n  constexpr auto WOLF_MINOR_VERSION = 0;\n  // bug fixes\n  constexpr auto WOLF_PATCH_VERSION = 0;\n  // for debugging\n  constexpr auto WOLF_DEBUG_VERSION = 0;\n\n  auto _version =\n      wolf::format(\"v{}.{}.{}.{}\", WOLF_MAJOR_VERSION, WOLF_MINOR_VERSION,\n                   WOLF_PATCH_VERSION, WOLF_DEBUG_VERSION);\n  return _version;\n}\n"
  },
  {
    "path": "wolf/wolf.hpp",
    "content": "/*\n    Project: Wolf Engine. Copyright © 2014-2023 Pooya Eimandar\n    https://github.com/WolfEngine/WolfEngine\n*/\n\n#pragma once\n\n#ifdef __SANITIZE_ADDRESS__\n#ifndef _DISABLE_VECTOR_ANNOTATION\n#define _DISABLE_VECTOR_ANNOTATION\n#endif\n#endif\n\n#ifdef _MSC_VER\n#include <codeanalysis\\warnings.h>\n#endif\n\n#ifdef WIN32\n#include <Windows.h>\n#endif\n\n#ifndef EMSCRIPTEN\n#include <filesystem>\n#endif\n\n#include <chrono>\n#include <exception>\n#include <memory>\n#include <optional>\n#include <sstream>\n#include <string>\n\n#include <boost/leaf.hpp>\n\n#ifdef _MSC_VER\n#include <format>\n#else\n#include <fmt/chrono.h>\n#include <fmt/format.h>\n#endif\n\n#include <gsl/gsl>\n\nconstexpr auto W_MAX_PATH = 260;\nconstexpr auto W_MAX_BUFFER_SIZE = 1024;\n\n#define DEFER auto _ = std::shared_ptr<void>(nullptr, [&](...)\n\nstruct w_buffer {\n  w_buffer() noexcept = default;\n\n  explicit w_buffer(const std::string_view p_str) { from_string(p_str); }\n\n  w_buffer(std::array<char, W_MAX_BUFFER_SIZE> &&p_array, const size_t p_used_bytes) noexcept {\n    this->buf = std::move(p_array);\n    this->used_bytes = p_used_bytes;\n  }\n\n  void from_string(const std::string_view p_str) {\n    const auto _size = p_str.size();\n    this->used_bytes = _size > 1024 ? 1024 : _size;\n    std::copy(p_str.cbegin(), p_str.cbegin() + this->used_bytes, buf.begin());\n  }\n\n  std::string to_string() {\n    if (this->buf.size() && this->used_bytes) {\n      return std::string(this->buf.data(), this->used_bytes);\n    }\n    return std::string();\n  }\n\n  std::array<char, W_MAX_BUFFER_SIZE> buf = {0};\n  size_t used_bytes = 0;\n};\n\n// #ifdef __clang__\n// #define W_ALIGNMENT_16 __attribute__((packed)) __attribute__((aligned(16)))\n// #define W_ALIGNMENT_32 __attribute__((packed)) __attribute__((aligned(32)))\n// #define W_ALIGNMENT_64 __attribute__((packed)) __attribute__((aligned(64)))\n// #define W_ALIGNMENT_128 __attribute__((packed)) __attribute__((aligned(128)))\n// #else\n// #define W_ALIGNMENT_16\n// #define W_ALIGNMENT_32\n// #define W_ALIGNMENT_64\n// #define W_ALIGNMENT_128\n// #endif\n\n#ifdef _MSC_VER\n\n#define W_API __declspec(dllexport)\n#define ASM __asm\n\n#else\n\n#define W_API\n#define ASM __asm__\n\n// define dummy SAL\n#define _In_\n#define _In_z_\n#define _Out_\n#define _Inout_\n#define _Inout_z_\n#define _In_opt_\n#define _In_opt_z_\n#define _Inout_opt_\n\n#endif\n\n#include <wolf/system/w_trace.hpp>\n#include <wolf/system/invocable.h>\n\nnamespace wolf {\n  template <class T>\n  using w_function = ofats::any_invocable<T>;\n  using w_binary = std::vector<std::byte>;\n\n/**\n * returns wolf version\n * @return string format with the following style\n * \"<major>.<minor>.<patch>.<debug>\"\n */\nW_API std::string w_init();\n\n/**\n * make a string via format\n * @param p_fmt, the fmt\n * @param p_args, the args\n * @return a string\n */\n#ifdef _MSC_VER\ntemplate <class... Args>\nW_API std::string format(_In_ const std::string_view p_fmt, _In_ Args &&...p_args) {\n  return std::vformat(p_fmt, std::make_format_args(std::forward<Args>(p_args)...));\n}\n#else\ntemplate <class... Args>\nW_API std::string format(_In_ const fmt::v9::format_string<Args...> p_fmt, _In_ Args &&...p_args) {\n  return fmt::v9::vformat(p_fmt, fmt::v9::make_format_args(p_args...));\n}\n#endif  // _MSC_VER\n}  // namespace wolf\n"
  },
  {
    "path": "wolf/wolf.ruleset",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RuleSet Name=\"wolf\" ToolsVersion=\"17.0\">\n  <Include Path=\"allrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"concurrencycheckrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"concurrencyrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckarithmeticrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckboundsrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckclassrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckconcurrencyrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckconstrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckdeclrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckenumrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckexperimentalrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckfuncrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckgslrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorechecklifetimerules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckownerpointerrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckrawpointerrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorechecksharedpointerrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckstlrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckstylerules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorechecktyperules.ruleset\" Action=\"Default\" />\n  <Include Path=\"cppcorecheckuniquepointerrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"nativeminimumrules.ruleset\" Action=\"Default\" />\n  <Include Path=\"nativerecommendedrules.ruleset\" Action=\"Default\" />\n</RuleSet>"
  },
  {
    "path": "wolf_demo/wasm/build.sh",
    "content": "#!/bin/sh\nem++ wolf.cpp \\\n-I./../../ \\\n-I./../../build/wasm32-unknown-emscripten/_deps/boost_leaf-src/include \\\n-I./../../build/wasm32-unknown-emscripten/_deps/fmt-src/include \\\n-I./../../build/wasm32-unknown-emscripten/_deps/gsl-src/include \\\n-L./../../build/wasm32-unknown-emscripten/wolf/ -lwolf \\\n-DWOLF_STREAM_JANUS \\\n-o ./www/wolf.js"
  },
  {
    "path": "wolf_demo/wasm/run.sh",
    "content": "#!/bin/sh\npython3 -m http.server 8000 --bind localhost --directory ./www/"
  },
  {
    "path": "wolf_demo/wasm/ssl_server.py",
    "content": "from http.server import HTTPServer, SimpleHTTPRequestHandler\nimport ssl\n\nhttpd = HTTPServer(('0.0.0.0', 8001), SimpleHTTPRequestHandler)\nhttpd.socket = ssl.wrap_socket(httpd.socket, certfile='cert.pem', server_side=True)\nhttpd.serve_forever()"
  },
  {
    "path": "wolf_demo/wasm/wolf.cpp",
    "content": "#include <emscripten/emscripten.h>\n#include <thread>\n#include <wolf/stream/janus/w_janus_api_emc.hpp>\n#include <wolf/wolf.hpp>\n\n#define JOIN\n\nusing w_janus_api_emc = wolf::stream::janus::w_janus_api_emc;\n\nint main() {\n  using namespace std::chrono_literals;\n\n  const auto _version = \"Wolf\" + wolf::w_init();\n  emscripten_log(EM_LOG_CONSOLE, _version.c_str());\n\n  constexpr auto _debug = true;\n  std::ignore = w_janus_api_emc::init(_debug, [](int p_init_state) {\n    if (p_init_state != 0) {\n      return;\n    }\n\n#ifdef JOIN\n    std::ignore = w_janus_api_emc::join_room(1259568387833386, \"wolf\", []() {\n      emscripten_log(EM_LOG_CONSOLE, \"joined\");\n    });\n#else\n    std::ignore = w_janus_api_emc::share_screen(\n        \"pooya\", \"screensharing test\", 500000, [](_In_ double p_room_id) {\n          const auto _room_id_str =\n              \"room id is: \" +\n              std::to_string(gsl::narrow_cast<uint64_t>(p_room_id));\n          emscripten_log(EM_LOG_CONSOLE, _room_id_str.c_str());\n        });\n#endif\n  });\n\n  return 0;\n}"
  },
  {
    "path": "wolf_demo/wasm/www/index.html",
    "content": "<!doctype html>\n<html lang=\"en-us\">\n\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n  <title>Wolf Janus API test</title>\n  <script type=\"text/javascript\"\n    src=\"https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js\"></script>\n  <script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js\"></script>\n  <script type=\"text/javascript\"\n    src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js\"></script>\n  <script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.min.js\"></script>\n</head>\n\n<body>\n  <button type=\"button\" style=\"margin: 3px 3px 3px 3px;\">Join</button>\n  <div></div>\n  <div id=\"streamscreen\"></div>\n  <script async>$(\"button\").click(function () {\n      $.getScript(\"janus_env.js\");\n      $.getScript(\"janus.js\");\n      $.getScript(\"wolf.js\");\n    }); </script>\n</body>\n\n</html>"
  },
  {
    "path": "wolf_demo/wasm/www/janus.js",
    "content": "\"use strict\";\n\n/*\n\tThe MIT License (MIT)\n\n\tCopyright (c) 2016 Meetecho\n\n\tPermission is hereby granted, free of charge, to any person obtaining\n\ta copy of this software and associated documentation files (the \"Software\"),\n\tto deal in the Software without restriction, including without limitation\n\tthe rights to use, copy, modify, merge, publish, distribute, sublicense,\n\tand/or sell copies of the Software, and to permit persons to whom the\n\tSoftware is furnished to do so, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included\n\tin all copies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n\tOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n\tTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n\tOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n\tARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n\tOTHER DEALINGS IN THE SOFTWARE.\n */\n\n// List of sessions\nJanus.sessions = {};\n\nJanus.isExtensionEnabled = function() {\n\tif(navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {\n\t\t// No need for the extension, getDisplayMedia is supported\n\t\treturn true;\n\t}\n\tif(window.navigator.userAgent.match('Chrome')) {\n\t\tlet chromever = parseInt(window.navigator.userAgent.match(/Chrome\\/(.*) /)[1], 10);\n\t\tlet maxver = 33;\n\t\tif(window.navigator.userAgent.match('Linux'))\n\t\t\tmaxver = 35;\t// \"known\" crash in chrome 34 and 35 on linux\n\t\tif(chromever >= 26 && chromever <= maxver) {\n\t\t\t// Older versions of Chrome don't support this extension-based approach, so lie\n\t\t\treturn true;\n\t\t}\n\t\treturn Janus.extension.isInstalled();\n\t} else {\n\t\t// Firefox and others, no need for the extension (but this doesn't mean it will work)\n\t\treturn true;\n\t}\n};\n\nvar defaultExtension = {\n\t// Screensharing Chrome Extension ID\n\textensionId: 'hapfgfdkleiggjjpfpenajgdnfckjpaj',\n\tisInstalled: function() { return document.querySelector('#janus-extension-installed') !== null; },\n\tgetScreen: function (callback) {\n\t\tlet pending = window.setTimeout(function () {\n\t\t\tlet error = new Error('NavigatorUserMediaError');\n\t\t\terror.name = 'The required Chrome extension is not installed: click <a href=\"#\">here</a> to install it. (NOTE: this will need you to refresh the page)';\n\t\t\treturn callback(error);\n\t\t}, 1000);\n\t\tthis.cache[pending] = callback;\n\t\twindow.postMessage({ type: 'janusGetScreen', id: pending }, '*');\n\t},\n\tinit: function () {\n\t\tlet cache = {};\n\t\tthis.cache = cache;\n\t\t// Wait for events from the Chrome Extension\n\t\twindow.addEventListener('message', function (event) {\n\t\t\tif(event.origin != window.location.origin)\n\t\t\t\treturn;\n\t\t\tif(event.data.type == 'janusGotScreen' && cache[event.data.id]) {\n\t\t\t\tlet callback = cache[event.data.id];\n\t\t\t\tdelete cache[event.data.id];\n\t\t\t\tif(event.data.sourceId === '') {\n\t\t\t\t\t// user canceled\n\t\t\t\t\tlet error = new Error('NavigatorUserMediaError');\n\t\t\t\t\terror.name = 'You cancelled the request for permission, giving up...';\n\t\t\t\t\tcallback(error);\n\t\t\t\t} else {\n\t\t\t\t\tcallback(null, event.data.sourceId);\n\t\t\t\t}\n\t\t\t} else if(event.data.type == 'janusGetScreenPending') {\n\t\t\t\tconsole.log('clearing ', event.data.id);\n\t\t\t\twindow.clearTimeout(event.data.id);\n\t\t\t}\n\t\t});\n\t}\n};\n\nJanus.useDefaultDependencies = function (deps) {\n\tlet f = (deps && deps.fetch) || fetch;\n\tlet p = (deps && deps.Promise) || Promise;\n\tlet socketCls = (deps && deps.WebSocket) || WebSocket;\n\n\treturn {\n\t\tnewWebSocket: function(server, proto) { return new socketCls(server, proto); },\n\t\textension: (deps && deps.extension) || defaultExtension,\n\t\tisArray: function(arr) { return Array.isArray(arr); },\n\t\twebRTCAdapter: (deps && deps.adapter) || adapter,\n\t\thttpAPICall: function(url, options) {\n\t\t\tlet fetchOptions = {\n\t\t\t\tmethod: options.verb,\n\t\t\t\theaders: {\n\t\t\t\t\t'Accept': 'application/json, text/plain, */*'\n\t\t\t\t},\n\t\t\t\tcache: 'no-cache'\n\t\t\t};\n\t\t\tif(options.verb === \"POST\") {\n\t\t\t\tfetchOptions.headers['Content-Type'] = 'application/json';\n\t\t\t}\n\t\t\tif(typeof options.withCredentials !== 'undefined') {\n\t\t\t\tfetchOptions.credentials = options.withCredentials === true ? 'include' : (options.withCredentials ? options.withCredentials : 'omit');\n\t\t\t}\n\t\t\tif(options.body) {\n\t\t\t\tfetchOptions.body = JSON.stringify(options.body);\n\t\t\t}\n\n\t\t\tlet fetching = f(url, fetchOptions).catch(function(error) {\n\t\t\t\treturn p.reject({message: 'Probably a network error, is the server down?', error: error});\n\t\t\t});\n\n\t\t\t/*\n\t\t\t * fetch() does not natively support timeouts.\n\t\t\t * Work around this by starting a timeout manually, and racing it agains the fetch() to see which thing resolves first.\n\t\t\t */\n\n\t\t\tif(options.timeout) {\n\t\t\t\tlet timeout = new p(function(resolve, reject) {\n\t\t\t\t\tlet timerId = setTimeout(function() {\n\t\t\t\t\t\tclearTimeout(timerId);\n\t\t\t\t\t\treturn reject({message: 'Request timed out', timeout: options.timeout});\n\t\t\t\t\t}, options.timeout);\n\t\t\t\t});\n\t\t\t\tfetching = p.race([fetching, timeout]);\n\t\t\t}\n\n\t\t\tfetching.then(function(response) {\n\t\t\t\tif(response.ok) {\n\t\t\t\t\tif(typeof(options.success) === typeof(Janus.noop)) {\n\t\t\t\t\t\treturn response.json().then(function(parsed) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\toptions.success(parsed);\n\t\t\t\t\t\t\t} catch(error) {\n\t\t\t\t\t\t\t\tJanus.error('Unhandled httpAPICall success callback error', error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, function(error) {\n\t\t\t\t\t\t\treturn p.reject({message: 'Failed to parse response body', error: error, response: response});\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\treturn p.reject({message: 'API call failed', response: response});\n\t\t\t\t}\n\t\t\t}).catch(function(error) {\n\t\t\t\tif(typeof(options.error) === typeof(Janus.noop)) {\n\t\t\t\t\toptions.error(error.message || '<< internal error >>', error);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn fetching;\n\t\t}\n\t}\n};\n\nJanus.useOldDependencies = function (deps) {\n\tlet jq = (deps && deps.jQuery) || jQuery;\n\tlet socketCls = (deps && deps.WebSocket) || WebSocket;\n\treturn {\n\t\tnewWebSocket: function(server, proto) { return new socketCls(server, proto); },\n\t\tisArray: function(arr) { return jq.isArray(arr); },\n\t\textension: (deps && deps.extension) || defaultExtension,\n\t\twebRTCAdapter: (deps && deps.adapter) || adapter,\n\t\thttpAPICall: function(url, options) {\n\t\t\tlet payload = (typeof options.body !== 'undefined') ? {\n\t\t\t\tcontentType: 'application/json',\n\t\t\t\tdata: JSON.stringify(options.body)\n\t\t\t} : {};\n\t\t\tlet credentials = (typeof options.withCredentials !== 'undefined') ? {xhrFields: {withCredentials: options.withCredentials}} : {};\n\n\t\t\treturn jq.ajax(jq.extend(payload, credentials, {\n\t\t\t\turl: url,\n\t\t\t\ttype: options.verb,\n\t\t\t\tcache: false,\n\t\t\t\tdataType: 'json',\n\t\t\t\tasync: options.async,\n\t\t\t\ttimeout: options.timeout,\n\t\t\t\tsuccess: function(result) {\n\t\t\t\t\tif(typeof(options.success) === typeof(Janus.noop)) {\n\t\t\t\t\t\toptions.success(result);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: function(xhr, status, err) {\n\t\t\t\t\tif(typeof(options.error) === typeof(Janus.noop)) {\n\t\t\t\t\t\toptions.error(status, err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\t};\n};\n\n// Helper function to convert a deprecated media object to a tracks array\nJanus.mediaToTracks = function(media) {\n\tlet tracks = [];\n\tif(!media) {\n\t\t// Default is bidirectional audio and video, using default devices\n\t\ttracks.push({ type: 'audio', capture: true, recv: true });\n\t\ttracks.push({ type: 'video', capture: true, recv: true });\n\t} else {\n\t\tif(!media.keepAudio && media.audio !== false && ((typeof media.audio === 'undefined') || media.audio || media.audioSend || media.audioRecv ||\n\t\t\t\tmedia.addAudio || media.replaceAudio || media.removeAudio)) {\n\t\t\t// We may need an audio track\n\t\t\tlet track = { type: 'audio' };\n\t\t\tif(media.removeAudio) {\n\t\t\t\ttrack.remove = true;\n\t\t\t} else {\n\t\t\t\tif(media.addAudio)\n\t\t\t\t\ttrack.add = true;\n\t\t\t\telse if(media.replaceAudio)\n\t\t\t\t\ttrack.replace = true;\n\t\t\t\t// Check if we need to capture an audio device\n\t\t\t\tif(media.audioSend !== false)\n\t\t\t\t\ttrack.capture = media.audio || true;\n\t\t\t\t// Check if we need to receive audio\n\t\t\t\tif(media.audioRecv !== false)\n\t\t\t\t\ttrack.recv = true;\n\t\t\t}\n\t\t\t// Add an audio track if needed\n\t\t\tif(track.remove || track.capture || track.recv)\n\t\t\t\ttracks.push(track);\n\t\t}\n\t\tif(!media.keepVideo && media.video !== false && ((typeof media.video === 'undefined') || media.video || media.videoSend || media.videoRecv ||\n\t\t\t\tmedia.addVideo || media.replaceVideo || media.removeVideo)) {\n\t\t\t// We may need a video track\n\t\t\tlet track = { type: 'video' };\n\t\t\tif(media.removeVideo) {\n\t\t\t\ttrack.remove = true;\n\t\t\t} else {\n\t\t\t\tif(media.addVideo)\n\t\t\t\t\ttrack.add = true;\n\t\t\t\telse if(media.replaceVideo)\n\t\t\t\t\ttrack.replace = true;\n\t\t\t\t// Check if we need to capture a video device\n\t\t\t\tif(media.videoSend !== false) {\n\t\t\t\t\ttrack.capture = media.video || true;\n\t\t\t\t\tif(['screen', 'window', 'desktop'].includes(track.capture)) {\n\t\t\t\t\t\t// Change the type to 'screen'\n\t\t\t\t\t\ttrack.type = 'screen';\n\t\t\t\t\t\ttrack.capture = { video: {} };\n\t\t\t\t\t\t// Check if there's constraints\n\t\t\t\t\t\tif(media.screenshareFrameRate)\n\t\t\t\t\t\t\ttrack.capture.frameRate = media.screenshareFrameRate;\n\t\t\t\t\t\tif(media.screenshareHeight)\n\t\t\t\t\t\t\ttrack.capture.height = media.screenshareHeight;\n\t\t\t\t\t\tif(media.screenshareWidth)\n\t\t\t\t\t\t\ttrack.capture.width = media.screenshareWidth;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Check if we need to receive video\n\t\t\t\tif(media.videoRecv !== false)\n\t\t\t\t\ttrack.recv = true;\n\t\t\t}\n\t\t\t// Add a video track if needed\n\t\t\tif(track.remove || track.capture || track.recv)\n\t\t\t\ttracks.push(track);\n\t\t}\n\t\tif(media.data) {\n\t\t\t// We need a data channel\n\t\t\ttracks.push({ type: 'data' });\n\t\t}\n\t}\n\t// Done\n\treturn tracks;\n};\n\n// Helper function to convert a track object to a set of constraints\nJanus.trackConstraints = function(track) {\n\tlet constraints = {};\n\tif(!track || !track.capture)\n\t\treturn constraints;\n\tif(track.type === 'audio') {\n\t\t// Just put the capture part in the constraints\n\t\tconstraints.audio = track.capture;\n\t} else if(track.type === 'video') {\n\t\t// Check if one of the keywords was passed\n\t\tif((track.simulcast || track.svc) && track.capture === true)\n\t\t\ttrack.capture = 'hires';\n\t\tif(track.capture === true || typeof track.capture === 'object') {\n\t\t\t// Use the provided capture object as video constraint\n\t\t\tconstraints.video = track.capture;\n\t\t} else {\n\t\t\tlet width = 0;\n\t\t\tlet height = 0;\n\t\t\tif(track.capture === 'lowres') {\n\t\t\t\t// Small resolution, 4:3\n\t\t\t\twidth = 320;\n\t\t\t\theight = 240;\n\t\t\t} else if(track.capture === 'lowres-16:9') {\n\t\t\t\t// Small resolution, 16:9\n\t\t\t\twidth = 320;\n\t\t\t\theight = 180;\n\t\t\t} else if(track.capture === 'hires' || track.capture === 'hires-16:9' || track.capture === 'hdres') {\n\t\t\t\t// High(HD) resolution is only 16:9\n\t\t\t\twidth = 1280;\n\t\t\t\theight = 720;\n\t\t\t} else if(track.capture === 'fhdres') {\n\t\t\t\t// Full HD resolution is only 16:9\n\t\t\t\twidth = 1920;\n\t\t\t\theight = 1080;\n\t\t\t} else if(track.capture === '4kres') {\n\t\t\t\t// 4K resolution is only 16:9\n\t\t\t\twidth = 3840;\n\t\t\t\theight = 2160;\n\t\t\t} else if(track.capture === 'stdres') {\n\t\t\t\t// Normal resolution, 4:3\n\t\t\t\twidth = 640;\n\t\t\t\theight = 480;\n\t\t\t} else if(track.capture === 'stdres-16:9') {\n\t\t\t\t// Normal resolution, 16:9\n\t\t\t\twidth = 640;\n\t\t\t\theight = 360;\n\t\t\t} else {\n\t\t\t\tJanus.log('Default video setting is stdres 4:3');\n\t\t\t\twidth = 640;\n\t\t\t\theight = 480;\n\t\t\t}\n\t\t\tconstraints.video = {\n\t\t\t\twidth: { ideal: width },\n\t\t\t\theight: { ideal: height }\n\t\t\t};\n\t\t}\n\t} else if(track.type === 'screen') {\n\t\t// Use the provided capture object as video constraint\n\t\tconstraints.video = track.capture;\n\t}\n\treturn constraints;\n};\n\nJanus.noop = function() {};\n\nJanus.dataChanDefaultLabel = \"JanusDataChannel\";\n\n// Note: in the future we may want to change this, e.g., as was\n// attempted in https://github.com/meetecho/janus-gateway/issues/1670\nJanus.endOfCandidates = null;\n\n// Stop all tracks from a given stream\nJanus.stopAllTracks = function(stream) {\n\ttry {\n\t\t// Try a MediaStreamTrack.stop() for each track\n\t\tlet tracks = stream.getTracks();\n\t\tfor(let mst of tracks) {\n\t\t\tJanus.log(mst);\n\t\t\tif(mst && mst.dontStop !== true) {\n\t\t\t\tmst.stop();\n\t\t\t}\n\t\t}\n\t} catch(e) {\n\t\t// Do nothing if this fails\n\t}\n}\n\n// Initialization\nJanus.init = function(options) {\n\toptions = options || {};\n\toptions.callback = (typeof options.callback == \"function\") ? options.callback : Janus.noop;\n\tif(Janus.initDone) {\n\t\t// Already initialized\n\t\toptions.callback();\n\t} else {\n\t\tif(typeof console.log == \"undefined\") {\n\t\t\tconsole.log = function() {};\n\t\t}\n\t\t// Console logging (all debugging disabled by default)\n\t\tJanus.trace = Janus.noop;\n\t\tJanus.debug = Janus.noop;\n\t\tJanus.vdebug = Janus.noop;\n\t\tJanus.log = Janus.noop;\n\t\tJanus.warn = Janus.noop;\n\t\tJanus.error = Janus.noop;\n\t\tif(options.debug === true || options.debug === \"all\") {\n\t\t\t// Enable all debugging levels\n\t\t\tJanus.trace = console.trace.bind(console);\n\t\t\tJanus.debug = console.debug.bind(console);\n\t\t\tJanus.vdebug = console.debug.bind(console);\n\t\t\tJanus.log = console.log.bind(console);\n\t\t\tJanus.warn = console.warn.bind(console);\n\t\t\tJanus.error = console.error.bind(console);\n\t\t} else if(Array.isArray(options.debug)) {\n\t\t\tfor(let d of options.debug) {\n\t\t\t\tswitch(d) {\n\t\t\t\t\tcase \"trace\":\n\t\t\t\t\t\tJanus.trace = console.trace.bind(console);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"debug\":\n\t\t\t\t\t\tJanus.debug = console.debug.bind(console);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"vdebug\":\n\t\t\t\t\t\tJanus.vdebug = console.debug.bind(console);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"log\":\n\t\t\t\t\t\tJanus.log = console.log.bind(console);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"warn\":\n\t\t\t\t\t\tJanus.warn = console.warn.bind(console);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\tJanus.error = console.error.bind(console);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tconsole.error(\"Unknown debugging option '\" + d + \"' (supported: 'trace', 'debug', 'vdebug', 'log', warn', 'error')\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tJanus.log(\"Initializing library\");\n\n\t\tlet usedDependencies = options.dependencies || Janus.useDefaultDependencies();\n\t\tJanus.isArray = usedDependencies.isArray;\n\t\tJanus.webRTCAdapter = usedDependencies.webRTCAdapter;\n\t\tJanus.httpAPICall = usedDependencies.httpAPICall;\n\t\tJanus.newWebSocket = usedDependencies.newWebSocket;\n\t\tJanus.extension = usedDependencies.extension;\n\t\tJanus.extension.init();\n\n\t\t// Helper method to enumerate devices\n\t\tJanus.listDevices = function(callback, config) {\n\t\t\tcallback = (typeof callback == \"function\") ? callback : Janus.noop;\n\t\t\tif(!config)\n\t\t\t\tconfig = { audio: true, video: true };\n\t\t\tif(Janus.isGetUserMediaAvailable()) {\n\t\t\t\tnavigator.mediaDevices.getUserMedia(config)\n\t\t\t\t.then(function(stream) {\n\t\t\t\t\tnavigator.mediaDevices.enumerateDevices().then(function(devices) {\n\t\t\t\t\t\tJanus.debug(devices);\n\t\t\t\t\t\tcallback(devices);\n\t\t\t\t\t\t// Get rid of the now useless stream\n\t\t\t\t\t\tJanus.stopAllTracks(stream)\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.catch(function(err) {\n\t\t\t\t\tJanus.error(err);\n\t\t\t\t\tcallback([]);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tJanus.warn(\"navigator.mediaDevices unavailable\");\n\t\t\t\tcallback([]);\n\t\t\t}\n\t\t};\n\t\t// Helper methods to attach/reattach a stream to a video element (previously part of adapter.js)\n\t\tJanus.attachMediaStream = function(element, stream) {\n\t\t\ttry {\n\t\t\t\telement.srcObject = stream;\n\t\t\t} catch (e) {\n\t\t\t\ttry {\n\t\t\t\t\telement.src = URL.createObjectURL(stream);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tJanus.error(\"Error attaching stream to element\", e);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tJanus.reattachMediaStream = function(to, from) {\n\t\t\ttry {\n\t\t\t\tto.srcObject = from.srcObject;\n\t\t\t} catch (e) {\n\t\t\t\ttry {\n\t\t\t\t\tto.src = from.src;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tJanus.error(\"Error reattaching stream to element\", e);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\t// Detect tab close: make sure we don't loose existing onbeforeunload handlers\n\t\t// (note: for iOS we need to subscribe to a different event, 'pagehide', see\n\t\t// https://gist.github.com/thehunmonkgroup/6bee8941a49b86be31a787fe8f4b8cfe)\n\t\tlet iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;\n\t\tlet eventName = iOS ? 'pagehide' : 'beforeunload';\n\t\tlet oldOBF = window[\"on\" + eventName];\n\t\twindow.addEventListener(eventName, function() {\n\t\t\tJanus.log(\"Closing window\");\n\t\t\tfor(let s in Janus.sessions) {\n\t\t\t\tif(Janus.sessions[s] && Janus.sessions[s].destroyOnUnload) {\n\t\t\t\t\tJanus.log(\"Destroying session \" + s);\n\t\t\t\t\tJanus.sessions[s].destroy({unload: true, notifyDestroyed: false});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(oldOBF && typeof oldOBF == \"function\") {\n\t\t\t\toldOBF();\n\t\t\t}\n\t\t});\n\t\t// If this is a Safari Technology Preview, check if VP8 is supported\n\t\tJanus.safariVp8 = false;\n\t\tif(Janus.webRTCAdapter.browserDetails.browser === 'safari' &&\n\t\t\t\tJanus.webRTCAdapter.browserDetails.version >= 605) {\n\t\t\t// Let's see if RTCRtpSender.getCapabilities() is there\n\t\t\tif(RTCRtpSender && RTCRtpSender.getCapabilities && RTCRtpSender.getCapabilities(\"video\") &&\n\t\t\t\t\tRTCRtpSender.getCapabilities(\"video\").codecs && RTCRtpSender.getCapabilities(\"video\").codecs.length) {\n\t\t\t\tfor(let codec of RTCRtpSender.getCapabilities(\"video\").codecs) {\n\t\t\t\t\tif(codec && codec.mimeType && codec.mimeType.toLowerCase() === \"video/vp8\") {\n\t\t\t\t\t\tJanus.safariVp8 = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(Janus.safariVp8) {\n\t\t\t\t\tJanus.log(\"This version of Safari supports VP8\");\n\t\t\t\t} else {\n\t\t\t\t\tJanus.warn(\"This version of Safari does NOT support VP8: if you're using a Technology Preview, \" +\n\t\t\t\t\t\t\"try enabling the 'WebRTC VP8 codec' setting in the 'Experimental Features' Develop menu\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We do it in a very ugly way, as there's no alternative...\n\t\t\t\t// We create a PeerConnection to see if VP8 is in an offer\n\t\t\t\tlet testpc = new RTCPeerConnection({});\n\t\t\t\ttestpc.createOffer({offerToReceiveVideo: true}).then(function(offer) {\n\t\t\t\t\tJanus.safariVp8 = offer.sdp.indexOf(\"VP8\") !== -1;\n\t\t\t\t\tif(Janus.safariVp8) {\n\t\t\t\t\t\tJanus.log(\"This version of Safari supports VP8\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tJanus.warn(\"This version of Safari does NOT support VP8: if you're using a Technology Preview, \" +\n\t\t\t\t\t\t\t\"try enabling the 'WebRTC VP8 codec' setting in the 'Experimental Features' Develop menu\");\n\t\t\t\t\t}\n\t\t\t\t\ttestpc.close();\n\t\t\t\t\ttestpc = null;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tJanus.initDone = true;\n\t\toptions.callback();\n\t}\n};\n\n// Helper method to check whether WebRTC is supported by this browser\nJanus.isWebrtcSupported = function() {\n\treturn !!window.RTCPeerConnection;\n};\n// Helper method to check whether devices can be accessed by this browser (e.g., not possible via plain HTTP)\nJanus.isGetUserMediaAvailable = function() {\n\treturn navigator.mediaDevices && navigator.mediaDevices.getUserMedia;\n};\n\n// Helper method to create random identifiers (e.g., transaction)\nJanus.randomString = function(len) {\n\tlet charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\tlet randomString = '';\n\tfor(let i=0; i<len; i++) {\n\t\tlet randomPoz = Math.floor(Math.random() * charSet.length);\n\t\trandomString += charSet.charAt(randomPoz);\n\t}\n\treturn randomString;\n};\n\nfunction Janus(gatewayCallbacks) {\n\tgatewayCallbacks = gatewayCallbacks || {};\n\tgatewayCallbacks.success = (typeof gatewayCallbacks.success == \"function\") ? gatewayCallbacks.success : Janus.noop;\n\tgatewayCallbacks.error = (typeof gatewayCallbacks.error == \"function\") ? gatewayCallbacks.error : Janus.noop;\n\tgatewayCallbacks.destroyed = (typeof gatewayCallbacks.destroyed == \"function\") ? gatewayCallbacks.destroyed : Janus.noop;\n\tif(!Janus.initDone) {\n\t\tgatewayCallbacks.error(\"Library not initialized\");\n\t\treturn {};\n\t}\n\tif(!Janus.isWebrtcSupported()) {\n\t\tgatewayCallbacks.error(\"WebRTC not supported by this browser\");\n\t\treturn {};\n\t}\n\tJanus.log(\"Library initialized: \" + Janus.initDone);\n\tif(!gatewayCallbacks.server) {\n\t\tgatewayCallbacks.error(\"Invalid server url\");\n\t\treturn {};\n\t}\n\tlet websockets = false;\n\tlet ws = null;\n\tlet wsHandlers = {};\n\tlet wsKeepaliveTimeoutId = null;\n\tlet servers = null;\n\tlet serversIndex = 0;\n\tlet server = gatewayCallbacks.server;\n\tif(Janus.isArray(server)) {\n\t\tJanus.log(\"Multiple servers provided (\" + server.length + \"), will use the first that works\");\n\t\tserver = null;\n\t\tservers = gatewayCallbacks.server;\n\t\tJanus.debug(servers);\n\t} else {\n\t\tif(server.indexOf(\"ws\") === 0) {\n\t\t\twebsockets = true;\n\t\t\tJanus.log(\"Using WebSockets to contact Janus: \" + server);\n\t\t} else {\n\t\t\twebsockets = false;\n\t\t\tJanus.log(\"Using REST API to contact Janus: \" + server);\n\t\t}\n\t}\n\tlet iceServers = gatewayCallbacks.iceServers || [{urls: \"stun:stun.l.google.com:19302\"}];\n\tlet iceTransportPolicy = gatewayCallbacks.iceTransportPolicy;\n\tlet bundlePolicy = gatewayCallbacks.bundlePolicy;\n\t// Whether we should enable the withCredentials flag for XHR requests\n\tlet withCredentials = false;\n\tif(typeof gatewayCallbacks.withCredentials !== 'undefined' && gatewayCallbacks.withCredentials !== null)\n\t\twithCredentials = gatewayCallbacks.withCredentials === true;\n\t// Optional max events\n\tlet maxev = 10;\n\tif(typeof gatewayCallbacks.max_poll_events !== 'undefined' && gatewayCallbacks.max_poll_events !== null)\n\t\tmaxev = gatewayCallbacks.max_poll_events;\n\tif(maxev < 1)\n\t\tmaxev = 1;\n\t// Token to use (only if the token based authentication mechanism is enabled)\n\tlet token = null;\n\tif(typeof gatewayCallbacks.token !== 'undefined' && gatewayCallbacks.token !== null)\n\t\ttoken = gatewayCallbacks.token;\n\t// API secret to use (only if the shared API secret is enabled)\n\tlet apisecret = null;\n\tif(typeof gatewayCallbacks.apisecret !== 'undefined' && gatewayCallbacks.apisecret !== null)\n\t\tapisecret = gatewayCallbacks.apisecret;\n\t// Whether we should destroy this session when onbeforeunload is called\n\tthis.destroyOnUnload = true;\n\tif(typeof gatewayCallbacks.destroyOnUnload !== 'undefined' && gatewayCallbacks.destroyOnUnload !== null)\n\t\tthis.destroyOnUnload = (gatewayCallbacks.destroyOnUnload === true);\n\t// Some timeout-related values\n\tlet keepAlivePeriod = 25000;\n\tif(typeof gatewayCallbacks.keepAlivePeriod !== 'undefined' && gatewayCallbacks.keepAlivePeriod !== null)\n\t\tkeepAlivePeriod = gatewayCallbacks.keepAlivePeriod;\n\tif(isNaN(keepAlivePeriod))\n\t\tkeepAlivePeriod = 25000;\n\tlet longPollTimeout = 60000;\n\tif(typeof gatewayCallbacks.longPollTimeout !== 'undefined' && gatewayCallbacks.longPollTimeout !== null)\n\t\tlongPollTimeout = gatewayCallbacks.longPollTimeout;\n\tif(isNaN(longPollTimeout))\n\t\tlongPollTimeout = 60000;\n\n\t// overrides for default maxBitrate values for simulcasting\n\tfunction getMaxBitrates(simulcastMaxBitrates) {\n\t\tlet maxBitrates = {\n\t\t\thigh: 900000,\n\t\t\tmedium: 300000,\n\t\t\tlow: 100000,\n\t\t};\n\n\t\tif(typeof simulcastMaxBitrates !== 'undefined' && simulcastMaxBitrates !== null) {\n\t\t\tif(simulcastMaxBitrates.high)\n\t\t\t\tmaxBitrates.high = simulcastMaxBitrates.high;\n\t\t\tif(simulcastMaxBitrates.medium)\n\t\t\t\tmaxBitrates.medium = simulcastMaxBitrates.medium;\n\t\t\tif(simulcastMaxBitrates.low)\n\t\t\t\tmaxBitrates.low = simulcastMaxBitrates.low;\n\t\t}\n\n\t\treturn maxBitrates;\n\t}\n\n\tlet connected = false;\n\tlet sessionId = null;\n\tlet pluginHandles = {};\n\tlet that = this;\n\tlet retries = 0;\n\tlet transactions = {};\n\tcreateSession(gatewayCallbacks);\n\n\t// Public methods\n\tthis.getServer = function() { return server; };\n\tthis.isConnected = function() { return connected; };\n\tthis.reconnect = function(callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tcallbacks[\"reconnect\"] = true;\n\t\tcreateSession(callbacks);\n\t};\n\tthis.getSessionId = function() { return sessionId; };\n\tthis.getInfo = function(callbacks) { getInfo(callbacks); };\n\tthis.destroy = function(callbacks) { destroySession(callbacks); };\n\tthis.attach = function(callbacks) { createHandle(callbacks); };\n\n\tfunction eventHandler() {\n\t\tif(sessionId == null)\n\t\t\treturn;\n\t\tJanus.debug('Long poll...');\n\t\tif(!connected) {\n\t\t\tJanus.warn(\"Is the server down? (connected=false)\");\n\t\t\treturn;\n\t\t}\n\t\tlet longpoll = server + \"/\" + sessionId + \"?rid=\" + new Date().getTime();\n\t\tif(maxev)\n\t\t\tlongpoll = longpoll + \"&maxev=\" + maxev;\n\t\tif(token)\n\t\t\tlongpoll = longpoll + \"&token=\" + encodeURIComponent(token);\n\t\tif(apisecret)\n\t\t\tlongpoll = longpoll + \"&apisecret=\" + encodeURIComponent(apisecret);\n\t\tJanus.httpAPICall(longpoll, {\n\t\t\tverb: 'GET',\n\t\t\twithCredentials: withCredentials,\n\t\t\tsuccess: handleEvent,\n\t\t\ttimeout: longPollTimeout,\n\t\t\terror: function(textStatus, errorThrown) {\n\t\t\t\tJanus.error(textStatus + \":\", errorThrown);\n\t\t\t\tretries++;\n\t\t\t\tif(retries > 3) {\n\t\t\t\t\t// Did we just lose the server? :-(\n\t\t\t\t\tconnected = false;\n\t\t\t\t\tgatewayCallbacks.error(\"Lost connection to the server (is it down?)\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\teventHandler();\n\t\t\t}\n\t\t});\n\t}\n\n\t// Private event handler: this will trigger plugin callbacks, if set\n\tfunction handleEvent(json, skipTimeout) {\n\t\tretries = 0;\n\t\tif(!websockets && typeof sessionId !== 'undefined' && sessionId !== null && skipTimeout !== true)\n\t\t\teventHandler();\n\t\tif(!websockets && Janus.isArray(json)) {\n\t\t\t// We got an array: it means we passed a maxev > 1, iterate on all objects\n\t\t\tfor(let i=0; i<json.length; i++) {\n\t\t\t\thandleEvent(json[i], true);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif(json[\"janus\"] === \"keepalive\") {\n\t\t\t// Nothing happened\n\t\t\tJanus.vdebug(\"Got a keepalive on session \" + sessionId);\n\t\t\treturn;\n\t\t} else if(json[\"janus\"] === \"server_info\") {\n\t\t\t// Just info on the Janus instance\n\t\t\tJanus.debug(\"Got info on the Janus instance\");\n\t\t\tJanus.debug(json);\n\t\t\tconst transaction = json[\"transaction\"];\n\t\t\tif(transaction) {\n\t\t\t\tconst reportSuccess = transactions[transaction];\n\t\t\t\tif(reportSuccess)\n\t\t\t\t\treportSuccess(json);\n\t\t\t\tdelete transactions[transaction];\n\t\t\t}\n\t\t\treturn;\n\t\t} else if(json[\"janus\"] === \"ack\") {\n\t\t\t// Just an ack, we can probably ignore\n\t\t\tJanus.debug(\"Got an ack on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\tconst transaction = json[\"transaction\"];\n\t\t\tif(transaction) {\n\t\t\t\tconst reportSuccess = transactions[transaction];\n\t\t\t\tif(reportSuccess)\n\t\t\t\t\treportSuccess(json);\n\t\t\t\tdelete transactions[transaction];\n\t\t\t}\n\t\t\treturn;\n\t\t} else if(json[\"janus\"] === \"success\") {\n\t\t\t// Success!\n\t\t\tJanus.debug(\"Got a success on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\tconst transaction = json[\"transaction\"];\n\t\t\tif(transaction) {\n\t\t\t\tconst reportSuccess = transactions[transaction];\n\t\t\t\tif(reportSuccess)\n\t\t\t\t\treportSuccess(json);\n\t\t\t\tdelete transactions[transaction];\n\t\t\t}\n\t\t\treturn;\n\t\t} else if(json[\"janus\"] === \"trickle\") {\n\t\t\t// We got a trickle candidate from Janus\n\t\t\tconst sender = json[\"sender\"];\n\t\t\tif(!sender) {\n\t\t\t\tJanus.warn(\"Missing sender...\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst pluginHandle = pluginHandles[sender];\n\t\t\tif(!pluginHandle) {\n\t\t\t\tJanus.debug(\"This handle is not attached to this session\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet candidate = json[\"candidate\"];\n\t\t\tJanus.debug(\"Got a trickled candidate on session \" + sessionId);\n\t\t\tJanus.debug(candidate);\n\t\t\tlet config = pluginHandle.webrtcStuff;\n\t\t\tif(config.pc && config.remoteSdp) {\n\t\t\t\t// Add candidate right now\n\t\t\t\tJanus.debug(\"Adding remote candidate:\", candidate);\n\t\t\t\tif(!candidate || candidate.completed === true) {\n\t\t\t\t\t// end-of-candidates\n\t\t\t\t\tconfig.pc.addIceCandidate(Janus.endOfCandidates);\n\t\t\t\t} else {\n\t\t\t\t\t// New candidate\n\t\t\t\t\tconfig.pc.addIceCandidate(candidate);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We didn't do setRemoteDescription (trickle got here before the offer?)\n\t\t\t\tJanus.debug(\"We didn't do setRemoteDescription (trickle got here before the offer?), caching candidate\");\n\t\t\t\tif(!config.candidates)\n\t\t\t\t\tconfig.candidates = [];\n\t\t\t\tconfig.candidates.push(candidate);\n\t\t\t\tJanus.debug(config.candidates);\n\t\t\t}\n\t\t} else if(json[\"janus\"] === \"webrtcup\") {\n\t\t\t// The PeerConnection with the server is up! Notify this\n\t\t\tJanus.debug(\"Got a webrtcup event on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\tconst sender = json[\"sender\"];\n\t\t\tif(!sender) {\n\t\t\t\tJanus.warn(\"Missing sender...\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst pluginHandle = pluginHandles[sender];\n\t\t\tif(!pluginHandle) {\n\t\t\t\tJanus.debug(\"This handle is not attached to this session\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpluginHandle.webrtcState(true);\n\t\t\treturn;\n\t\t} else if(json[\"janus\"] === \"hangup\") {\n\t\t\t// A plugin asked the core to hangup a PeerConnection on one of our handles\n\t\t\tJanus.debug(\"Got a hangup event on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\tconst sender = json[\"sender\"];\n\t\t\tif(!sender) {\n\t\t\t\tJanus.warn(\"Missing sender...\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst pluginHandle = pluginHandles[sender];\n\t\t\tif(!pluginHandle) {\n\t\t\t\tJanus.debug(\"This handle is not attached to this session\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpluginHandle.webrtcState(false, json[\"reason\"]);\n\t\t\tpluginHandle.hangup();\n\t\t} else if(json[\"janus\"] === \"detached\") {\n\t\t\t// A plugin asked the core to detach one of our handles\n\t\t\tJanus.debug(\"Got a detached event on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\tconst sender = json[\"sender\"];\n\t\t\tif(!sender) {\n\t\t\t\tJanus.warn(\"Missing sender...\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst pluginHandle = pluginHandles[sender];\n\t\t\tif(!pluginHandle) {\n\t\t\t\t// Don't warn here because destroyHandle causes this situation.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpluginHandle.ondetached();\n\t\t\tpluginHandle.detach();\n\t\t} else if(json[\"janus\"] === \"media\") {\n\t\t\t// Media started/stopped flowing\n\t\t\tJanus.debug(\"Got a media event on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\tconst sender = json[\"sender\"];\n\t\t\tif(!sender) {\n\t\t\t\tJanus.warn(\"Missing sender...\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst pluginHandle = pluginHandles[sender];\n\t\t\tif(!pluginHandle) {\n\t\t\t\tJanus.debug(\"This handle is not attached to this session\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpluginHandle.mediaState(json[\"type\"], json[\"receiving\"], json[\"mid\"]);\n\t\t} else if(json[\"janus\"] === \"slowlink\") {\n\t\t\tJanus.debug(\"Got a slowlink event on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\t// Trouble uplink or downlink\n\t\t\tconst sender = json[\"sender\"];\n\t\t\tif(!sender) {\n\t\t\t\tJanus.warn(\"Missing sender...\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst pluginHandle = pluginHandles[sender];\n\t\t\tif(!pluginHandle) {\n\t\t\t\tJanus.debug(\"This handle is not attached to this session\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpluginHandle.slowLink(json[\"uplink\"], json[\"lost\"], json[\"mid\"]);\n\t\t} else if(json[\"janus\"] === \"error\") {\n\t\t\t// Oops, something wrong happened\n\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\tJanus.debug(json);\n\t\t\tlet transaction = json[\"transaction\"];\n\t\t\tif(transaction) {\n\t\t\t\tlet reportSuccess = transactions[transaction];\n\t\t\t\tif(reportSuccess) {\n\t\t\t\t\treportSuccess(json);\n\t\t\t\t}\n\t\t\t\tdelete transactions[transaction];\n\t\t\t}\n\t\t\treturn;\n\t\t} else if(json[\"janus\"] === \"event\") {\n\t\t\tJanus.debug(\"Got a plugin event on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\tconst sender = json[\"sender\"];\n\t\t\tif(!sender) {\n\t\t\t\tJanus.warn(\"Missing sender...\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet plugindata = json[\"plugindata\"];\n\t\t\tif(!plugindata) {\n\t\t\t\tJanus.warn(\"Missing plugindata...\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tJanus.debug(\"  -- Event is coming from \" + sender + \" (\" + plugindata[\"plugin\"] + \")\");\n\t\t\tlet data = plugindata[\"data\"];\n\t\t\tJanus.debug(data);\n\t\t\tconst pluginHandle = pluginHandles[sender];\n\t\t\tif(!pluginHandle) {\n\t\t\t\tJanus.warn(\"This handle is not attached to this session\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet jsep = json[\"jsep\"];\n\t\t\tif(jsep) {\n\t\t\t\tJanus.debug(\"Handling SDP as well...\");\n\t\t\t\tJanus.debug(jsep);\n\t\t\t}\n\t\t\tlet callback = pluginHandle.onmessage;\n\t\t\tif(callback) {\n\t\t\t\tJanus.debug(\"Notifying application...\");\n\t\t\t\t// Send to callback specified when attaching plugin handle\n\t\t\t\tcallback(data, jsep);\n\t\t\t} else {\n\t\t\t\t// Send to generic callback (?)\n\t\t\t\tJanus.debug(\"No provided notification callback\");\n\t\t\t}\n\t\t} else if(json[\"janus\"] === \"timeout\") {\n\t\t\tJanus.error(\"Timeout on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t\tif(websockets) {\n\t\t\t\tws.close(3504, \"Gateway timeout\");\n\t\t\t}\n\t\t\treturn;\n\t\t} else {\n\t\t\tJanus.warn(\"Unknown message/event  '\" + json[\"janus\"] + \"' on session \" + sessionId);\n\t\t\tJanus.debug(json);\n\t\t}\n\t}\n\n\t// Private helper to send keep-alive messages on WebSockets\n\tfunction keepAlive() {\n\t\tif(!server || !websockets || !connected)\n\t\t\treturn;\n\t\twsKeepaliveTimeoutId = setTimeout(keepAlive, keepAlivePeriod);\n\t\tlet request = { \"janus\": \"keepalive\", \"session_id\": sessionId, \"transaction\": Janus.randomString(12) };\n\t\tif(token)\n\t\t\trequest[\"token\"] = token;\n\t\tif(apisecret)\n\t\t\trequest[\"apisecret\"] = apisecret;\n\t\tws.send(JSON.stringify(request));\n\t}\n\n\t// Private method to create a session\n\tfunction createSession(callbacks) {\n\t\tlet transaction = Janus.randomString(12);\n\t\tlet request = { \"janus\": \"create\", \"transaction\": transaction };\n\t\tif(callbacks[\"reconnect\"]) {\n\t\t\t// We're reconnecting, claim the session\n\t\t\tconnected = false;\n\t\t\trequest[\"janus\"] = \"claim\";\n\t\t\trequest[\"session_id\"] = sessionId;\n\t\t\t// If we were using websockets, ignore the old connection\n\t\t\tif(ws) {\n\t\t\t\tws.onopen = null;\n\t\t\t\tws.onerror = null;\n\t\t\t\tws.onclose = null;\n\t\t\t\tif(wsKeepaliveTimeoutId) {\n\t\t\t\t\tclearTimeout(wsKeepaliveTimeoutId);\n\t\t\t\t\twsKeepaliveTimeoutId = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(token)\n\t\t\trequest[\"token\"] = token;\n\t\tif(apisecret)\n\t\t\trequest[\"apisecret\"] = apisecret;\n\t\tif(!server && Janus.isArray(servers)) {\n\t\t\t// We still need to find a working server from the list we were given\n\t\t\tserver = servers[serversIndex];\n\t\t\tif(server.indexOf(\"ws\") === 0) {\n\t\t\t\twebsockets = true;\n\t\t\t\tJanus.log(\"Server #\" + (serversIndex+1) + \": trying WebSockets to contact Janus (\" + server + \")\");\n\t\t\t} else {\n\t\t\t\twebsockets = false;\n\t\t\t\tJanus.log(\"Server #\" + (serversIndex+1) + \": trying REST API to contact Janus (\" + server + \")\");\n\t\t\t}\n\t\t}\n\t\tif(websockets) {\n\t\t\tws = Janus.newWebSocket(server, 'janus-protocol');\n\t\t\twsHandlers = {\n\t\t\t\t'error': function() {\n\t\t\t\t\tJanus.error(\"Error connecting to the Janus WebSockets server... \" + server);\n\t\t\t\t\tif(Janus.isArray(servers) && !callbacks[\"reconnect\"]) {\n\t\t\t\t\t\tserversIndex++;\n\t\t\t\t\t\tif(serversIndex === servers.length) {\n\t\t\t\t\t\t\t// We tried all the servers the user gave us and they all failed\n\t\t\t\t\t\t\tcallbacks.error(\"Error connecting to any of the provided Janus servers: Is the server down?\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Let's try the next server\n\t\t\t\t\t\tserver = null;\n\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\tcreateSession(callbacks);\n\t\t\t\t\t\t}, 200);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcallbacks.error(\"Error connecting to the Janus WebSockets server: Is the server down?\");\n\t\t\t\t},\n\n\t\t\t\t'open': function() {\n\t\t\t\t\t// We need to be notified about the success\n\t\t\t\t\ttransactions[transaction] = function(json) {\n\t\t\t\t\t\tJanus.debug(json);\n\t\t\t\t\t\tif(json[\"janus\"] !== \"success\") {\n\t\t\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t\t\t\tcallbacks.error(json[\"error\"].reason);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\twsKeepaliveTimeoutId = setTimeout(keepAlive, keepAlivePeriod);\n\t\t\t\t\t\tconnected = true;\n\t\t\t\t\t\tsessionId = json[\"session_id\"] ? json[\"session_id\"] : json.data[\"id\"];\n\t\t\t\t\t\tif(callbacks[\"reconnect\"]) {\n\t\t\t\t\t\t\tJanus.log(\"Claimed session: \" + sessionId);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tJanus.log(\"Created session: \" + sessionId);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tJanus.sessions[sessionId] = that;\n\t\t\t\t\t\tcallbacks.success();\n\t\t\t\t\t};\n\t\t\t\t\tws.send(JSON.stringify(request));\n\t\t\t\t},\n\n\t\t\t\t'message': function(event) {\n\t\t\t\t\thandleEvent(JSON.parse(event.data));\n\t\t\t\t},\n\n\t\t\t\t'close': function() {\n\t\t\t\t\tif(!server || !connected) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconnected = false;\n\t\t\t\t\t// FIXME What if this is called when the page is closed?\n\t\t\t\t\tgatewayCallbacks.error(\"Lost connection to the server (is it down?)\");\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor(let eventName in wsHandlers) {\n\t\t\t\tws.addEventListener(eventName, wsHandlers[eventName]);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tJanus.httpAPICall(server, {\n\t\t\tverb: 'POST',\n\t\t\twithCredentials: withCredentials,\n\t\t\tbody: request,\n\t\t\tsuccess: function(json) {\n\t\t\t\tJanus.debug(json);\n\t\t\t\tif(json[\"janus\"] !== \"success\") {\n\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t\tcallbacks.error(json[\"error\"].reason);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconnected = true;\n\t\t\t\tsessionId = json[\"session_id\"] ? json[\"session_id\"] : json.data[\"id\"];\n\t\t\t\tif(callbacks[\"reconnect\"]) {\n\t\t\t\t\tJanus.log(\"Claimed session: \" + sessionId);\n\t\t\t\t} else {\n\t\t\t\t\tJanus.log(\"Created session: \" + sessionId);\n\t\t\t\t}\n\t\t\t\tJanus.sessions[sessionId] = that;\n\t\t\t\teventHandler();\n\t\t\t\tcallbacks.success();\n\t\t\t},\n\t\t\terror: function(textStatus, errorThrown) {\n\t\t\t\tJanus.error(textStatus + \":\", errorThrown);\t// FIXME\n\t\t\t\tif(Janus.isArray(servers) && !callbacks[\"reconnect\"]) {\n\t\t\t\t\tserversIndex++;\n\t\t\t\t\tif(serversIndex === servers.length) {\n\t\t\t\t\t\t// We tried all the servers the user gave us and they all failed\n\t\t\t\t\t\tcallbacks.error(\"Error connecting to any of the provided Janus servers: Is the server down?\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Let's try the next server\n\t\t\t\t\tserver = null;\n\t\t\t\t\tsetTimeout(function() { createSession(callbacks); }, 200);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif(errorThrown === \"\")\n\t\t\t\t\tcallbacks.error(textStatus + \": Is the server down?\");\n\t\t\t\telse if(errorThrown && errorThrown.error)\n\t\t\t\t\tcallbacks.error(textStatus + \": \" + errorThrown.error.message);\n\t\t\t\telse\n\t\t\t\t\tcallbacks.error(textStatus + \": \" + errorThrown);\n\t\t\t}\n\t\t});\n\t}\n\n\t// Private method to get info on the server\n\tfunction getInfo(callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\t// FIXME This method triggers a success even when we fail\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tJanus.log(\"Getting info on Janus instance\");\n\t\tif(!connected) {\n\t\t\tJanus.warn(\"Is the server down? (connected=false)\");\n\t\t\tcallbacks.error(\"Is the server down? (connected=false)\");\n\t\t\treturn;\n\t\t}\n\t\t// We just need to send an \"info\" request\n\t\tlet transaction = Janus.randomString(12);\n\t\tlet request = { \"janus\": \"info\", \"transaction\": transaction };\n\t\tif(token)\n\t\t\trequest[\"token\"] = token;\n\t\tif(apisecret)\n\t\t\trequest[\"apisecret\"] = apisecret;\n\t\tif(websockets) {\n\t\t\ttransactions[transaction] = function(json) {\n\t\t\t\tJanus.log(\"Server info:\");\n\t\t\t\tJanus.debug(json);\n\t\t\t\tif(json[\"janus\"] !== \"server_info\") {\n\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t}\n\t\t\t\tcallbacks.success(json);\n\t\t\t}\n\t\t\tws.send(JSON.stringify(request));\n\t\t\treturn;\n\t\t}\n\t\tJanus.httpAPICall(server, {\n\t\t\tverb: 'POST',\n\t\t\twithCredentials: withCredentials,\n\t\t\tbody: request,\n\t\t\tsuccess: function(json) {\n\t\t\t\tJanus.log(\"Server info:\");\n\t\t\t\tJanus.debug(json);\n\t\t\t\tif(json[\"janus\"] !== \"server_info\") {\n\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t}\n\t\t\t\tcallbacks.success(json);\n\t\t\t},\n\t\t\terror: function(textStatus, errorThrown) {\n\t\t\t\tJanus.error(textStatus + \":\", errorThrown);\t// FIXME\n\t\t\t\tif(errorThrown === \"\")\n\t\t\t\t\tcallbacks.error(textStatus + \": Is the server down?\");\n\t\t\t\telse\n\t\t\t\t\tcallbacks.error(textStatus + \": \" + errorThrown);\n\t\t\t}\n\t\t});\n\t}\n\n\t// Private method to destroy a session\n\tfunction destroySession(callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\t// FIXME This method triggers a success even when we fail\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tlet unload = (callbacks.unload === true);\n\t\tlet notifyDestroyed = true;\n\t\tif(typeof callbacks.notifyDestroyed !== 'undefined' && callbacks.notifyDestroyed !== null)\n\t\t\tnotifyDestroyed = (callbacks.notifyDestroyed === true);\n\t\tlet cleanupHandles = (callbacks.cleanupHandles === true);\n\t\tJanus.log(\"Destroying session \" + sessionId + \" (unload=\" + unload + \")\");\n\t\tif(!sessionId) {\n\t\t\tJanus.warn(\"No session to destroy\");\n\t\t\tcallbacks.success();\n\t\t\tif(notifyDestroyed)\n\t\t\t\tgatewayCallbacks.destroyed();\n\t\t\treturn;\n\t\t}\n\t\tif(cleanupHandles) {\n\t\t\tfor(let handleId in pluginHandles)\n\t\t\t\tdestroyHandle(handleId, { noRequest: true });\n\t\t}\n\t\tif(!connected) {\n\t\t\tJanus.warn(\"Is the server down? (connected=false)\");\n\t\t\tsessionId = null;\n\t\t\tcallbacks.success();\n\t\t\treturn;\n\t\t}\n\t\t// No need to destroy all handles first, Janus will do that itself\n\t\tlet request = { \"janus\": \"destroy\", \"transaction\": Janus.randomString(12) };\n\t\tif(token)\n\t\t\trequest[\"token\"] = token;\n\t\tif(apisecret)\n\t\t\trequest[\"apisecret\"] = apisecret;\n\t\tif(unload) {\n\t\t\t// We're unloading the page: use sendBeacon for HTTP instead,\n\t\t\t// or just close the WebSocket connection if we're using that\n\t\t\tif(websockets) {\n\t\t\t\tws.onclose = null;\n\t\t\t\tws.close();\n\t\t\t\tws = null;\n\t\t\t} else {\n\t\t\t\tnavigator.sendBeacon(server + \"/\" + sessionId, JSON.stringify(request));\n\t\t\t}\n\t\t\tJanus.log(\"Destroyed session:\");\n\t\t\tsessionId = null;\n\t\t\tconnected = false;\n\t\t\tcallbacks.success();\n\t\t\tif(notifyDestroyed)\n\t\t\t\tgatewayCallbacks.destroyed();\n\t\t\treturn;\n\t\t}\n\t\tif(websockets) {\n\t\t\trequest[\"session_id\"] = sessionId;\n\n\t\t\tlet unbindWebSocket = function() {\n\t\t\t\tfor(let eventName in wsHandlers) {\n\t\t\t\t\tws.removeEventListener(eventName, wsHandlers[eventName]);\n\t\t\t\t}\n\t\t\t\tws.removeEventListener('message', onUnbindMessage);\n\t\t\t\tws.removeEventListener('error', onUnbindError);\n\t\t\t\tif(wsKeepaliveTimeoutId) {\n\t\t\t\t\tclearTimeout(wsKeepaliveTimeoutId);\n\t\t\t\t}\n\t\t\t\tws.close();\n\t\t\t};\n\n\t\t\tlet onUnbindMessage = function(event){\n\t\t\t\tlet data = JSON.parse(event.data);\n\t\t\t\tif(data.session_id == request.session_id && data.transaction == request.transaction) {\n\t\t\t\t\tunbindWebSocket();\n\t\t\t\t\tcallbacks.success();\n\t\t\t\t\tif(notifyDestroyed)\n\t\t\t\t\t\tgatewayCallbacks.destroyed();\n\t\t\t\t}\n\t\t\t};\n\t\t\tlet onUnbindError = function() {\n\t\t\t\tunbindWebSocket();\n\t\t\t\tcallbacks.error(\"Failed to destroy the server: Is the server down?\");\n\t\t\t\tif(notifyDestroyed)\n\t\t\t\t\tgatewayCallbacks.destroyed();\n\t\t\t};\n\n\t\t\tws.addEventListener('message', onUnbindMessage);\n\t\t\tws.addEventListener('error', onUnbindError);\n\n\t\t\tif(ws.readyState === 1) {\n\t\t\t\tws.send(JSON.stringify(request));\n\t\t\t} else {\n\t\t\t\tonUnbindError();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\tJanus.httpAPICall(server + \"/\" + sessionId, {\n\t\t\tverb: 'POST',\n\t\t\twithCredentials: withCredentials,\n\t\t\tbody: request,\n\t\t\tsuccess: function(json) {\n\t\t\t\tJanus.log(\"Destroyed session:\");\n\t\t\t\tJanus.debug(json);\n\t\t\t\tsessionId = null;\n\t\t\t\tconnected = false;\n\t\t\t\tif(json[\"janus\"] !== \"success\") {\n\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t}\n\t\t\t\tcallbacks.success();\n\t\t\t\tif(notifyDestroyed)\n\t\t\t\t\tgatewayCallbacks.destroyed();\n\t\t\t},\n\t\t\terror: function(textStatus, errorThrown) {\n\t\t\t\tJanus.error(textStatus + \":\", errorThrown);\t// FIXME\n\t\t\t\t// Reset everything anyway\n\t\t\t\tsessionId = null;\n\t\t\t\tconnected = false;\n\t\t\t\tcallbacks.success();\n\t\t\t\tif(notifyDestroyed)\n\t\t\t\t\tgatewayCallbacks.destroyed();\n\t\t\t}\n\t\t});\n\t}\n\n\t// Private method to create a plugin handle\n\tfunction createHandle(callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tcallbacks.dataChannelOptions = callbacks.dataChannelOptions || { ordered: true };\n\t\tcallbacks.consentDialog = (typeof callbacks.consentDialog == \"function\") ? callbacks.consentDialog : Janus.noop;\n\t\tcallbacks.iceState = (typeof callbacks.iceState == \"function\") ? callbacks.iceState : Janus.noop;\n\t\tcallbacks.mediaState = (typeof callbacks.mediaState == \"function\") ? callbacks.mediaState : Janus.noop;\n\t\tcallbacks.webrtcState = (typeof callbacks.webrtcState == \"function\") ? callbacks.webrtcState : Janus.noop;\n\t\tcallbacks.slowLink = (typeof callbacks.slowLink == \"function\") ? callbacks.slowLink : Janus.noop;\n\t\tcallbacks.onmessage = (typeof callbacks.onmessage == \"function\") ? callbacks.onmessage : Janus.noop;\n\t\tcallbacks.onlocaltrack = (typeof callbacks.onlocaltrack == \"function\") ? callbacks.onlocaltrack : Janus.noop;\n\t\tcallbacks.onremotetrack = (typeof callbacks.onremotetrack == \"function\") ? callbacks.onremotetrack : Janus.noop;\n\t\tcallbacks.ondata = (typeof callbacks.ondata == \"function\") ? callbacks.ondata : Janus.noop;\n\t\tcallbacks.ondataopen = (typeof callbacks.ondataopen == \"function\") ? callbacks.ondataopen : Janus.noop;\n\t\tcallbacks.oncleanup = (typeof callbacks.oncleanup == \"function\") ? callbacks.oncleanup : Janus.noop;\n\t\tcallbacks.ondetached = (typeof callbacks.ondetached == \"function\") ? callbacks.ondetached : Janus.noop;\n\t\tif(!connected) {\n\t\t\tJanus.warn(\"Is the server down? (connected=false)\");\n\t\t\tcallbacks.error(\"Is the server down? (connected=false)\");\n\t\t\treturn;\n\t\t}\n\t\tlet plugin = callbacks.plugin;\n\t\tif(!plugin) {\n\t\t\tJanus.error(\"Invalid plugin\");\n\t\t\tcallbacks.error(\"Invalid plugin\");\n\t\t\treturn;\n\t\t}\n\t\tlet opaqueId = callbacks.opaqueId;\n\t\tlet loopIndex = callbacks.loopIndex;\n\t\tlet handleToken = callbacks.token ? callbacks.token : token;\n\t\tlet transaction = Janus.randomString(12);\n\t\tlet request = { \"janus\": \"attach\", \"plugin\": plugin, \"opaque_id\": opaqueId, \"loop_index\": loopIndex, \"transaction\": transaction };\n\t\tif(handleToken)\n\t\t\trequest[\"token\"] = handleToken;\n\t\tif(apisecret)\n\t\t\trequest[\"apisecret\"] = apisecret;\n\t\tif(websockets) {\n\t\t\ttransactions[transaction] = function(json) {\n\t\t\t\tJanus.debug(json);\n\t\t\t\tif(json[\"janus\"] !== \"success\") {\n\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t\tcallbacks.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet handleId = json.data[\"id\"];\n\t\t\t\tJanus.log(\"Created handle: \" + handleId);\n\t\t\t\tlet pluginHandle =\n\t\t\t\t\t{\n\t\t\t\t\t\tsession : that,\n\t\t\t\t\t\tplugin : plugin,\n\t\t\t\t\t\tid : handleId,\n\t\t\t\t\t\ttoken : handleToken,\n\t\t\t\t\t\tdetached : false,\n\t\t\t\t\t\twebrtcStuff : {\n\t\t\t\t\t\t\tstarted : false,\n\t\t\t\t\t\t\tmyStream : null,\n\t\t\t\t\t\t\tstreamExternal : false,\n\t\t\t\t\t\t\tmySdp : null,\n\t\t\t\t\t\t\tmediaConstraints : null,\n\t\t\t\t\t\t\tpc : null,\n\t\t\t\t\t\t\tdataChannelOptions: callbacks.dataChannelOptions,\n\t\t\t\t\t\t\tdataChannel : {},\n\t\t\t\t\t\t\tdtmfSender : null,\n\t\t\t\t\t\t\ttrickle : true,\n\t\t\t\t\t\t\ticeDone : false,\n\t\t\t\t\t\t\tbitrate : {}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgetId : function() { return handleId; },\n\t\t\t\t\t\tgetPlugin : function() { return plugin; },\n\t\t\t\t\t\tgetVolume : function(mid, result) { return getVolume(handleId, mid, true, result); },\n\t\t\t\t\t\tgetRemoteVolume : function(mid, result) { return getVolume(handleId, mid, true, result); },\n\t\t\t\t\t\tgetLocalVolume : function(mid, result) { return getVolume(handleId, mid, false, result); },\n\t\t\t\t\t\tisAudioMuted : function(mid) { return isMuted(handleId, mid, false); },\n\t\t\t\t\t\tmuteAudio : function(mid) { return mute(handleId, mid, false, true); },\n\t\t\t\t\t\tunmuteAudio : function(mid) { return mute(handleId, mid, false, false); },\n\t\t\t\t\t\tisVideoMuted : function(mid) { return isMuted(handleId, mid, true); },\n\t\t\t\t\t\tmuteVideo : function(mid) { return mute(handleId, mid, true, true); },\n\t\t\t\t\t\tunmuteVideo : function(mid) { return mute(handleId, mid, true, false); },\n\t\t\t\t\t\tgetBitrate : function(mid) { return getBitrate(handleId, mid); },\n\t\t\t\t\t\tsetMaxBitrate : function(mid, bitrate) { return setBitrate(handleId, mid, bitrate); },\n\t\t\t\t\t\tsend : function(callbacks) { sendMessage(handleId, callbacks); },\n\t\t\t\t\t\tdata : function(callbacks) { sendData(handleId, callbacks); },\n\t\t\t\t\t\tdtmf : function(callbacks) { sendDtmf(handleId, callbacks); },\n\t\t\t\t\t\tconsentDialog : callbacks.consentDialog,\n\t\t\t\t\t\ticeState : callbacks.iceState,\n\t\t\t\t\t\tmediaState : callbacks.mediaState,\n\t\t\t\t\t\twebrtcState : callbacks.webrtcState,\n\t\t\t\t\t\tslowLink : callbacks.slowLink,\n\t\t\t\t\t\tonmessage : callbacks.onmessage,\n\t\t\t\t\t\tcreateOffer : function(callbacks) { prepareWebrtc(handleId, true, callbacks); },\n\t\t\t\t\t\tcreateAnswer : function(callbacks) { prepareWebrtc(handleId, false, callbacks); },\n\t\t\t\t\t\thandleRemoteJsep : function(callbacks) { prepareWebrtcPeer(handleId, callbacks); },\n\t\t\t\t\t\treplaceTracks : function(callbacks) { replaceTracks(handleId, callbacks); },\n\t\t\t\t\t\tgetLocalTracks : function() { return getLocalTracks(handleId); },\n\t\t\t\t\t\tgetRemoteTracks : function() { return getRemoteTracks(handleId); },\n\t\t\t\t\t\tonlocaltrack : callbacks.onlocaltrack,\n\t\t\t\t\t\tonremotetrack : callbacks.onremotetrack,\n\t\t\t\t\t\tondata : callbacks.ondata,\n\t\t\t\t\t\tondataopen : callbacks.ondataopen,\n\t\t\t\t\t\toncleanup : callbacks.oncleanup,\n\t\t\t\t\t\tondetached : callbacks.ondetached,\n\t\t\t\t\t\thangup : function(sendRequest) { cleanupWebrtc(handleId, sendRequest === true); },\n\t\t\t\t\t\tdetach : function(callbacks) { destroyHandle(handleId, callbacks); }\n\t\t\t\t\t};\n\t\t\t\tpluginHandles[handleId] = pluginHandle;\n\t\t\t\tcallbacks.success(pluginHandle);\n\t\t\t};\n\t\t\trequest[\"session_id\"] = sessionId;\n\t\t\tws.send(JSON.stringify(request));\n\t\t\treturn;\n\t\t}\n\t\tJanus.httpAPICall(server + \"/\" + sessionId, {\n\t\t\tverb: 'POST',\n\t\t\twithCredentials: withCredentials,\n\t\t\tbody: request,\n\t\t\tsuccess: function(json) {\n\t\t\t\tJanus.debug(json);\n\t\t\t\tif(json[\"janus\"] !== \"success\") {\n\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t\tcallbacks.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet handleId = json.data[\"id\"];\n\t\t\t\tJanus.log(\"Created handle: \" + handleId);\n\t\t\t\tlet pluginHandle =\n\t\t\t\t\t{\n\t\t\t\t\t\tsession : that,\n\t\t\t\t\t\tplugin : plugin,\n\t\t\t\t\t\tid : handleId,\n\t\t\t\t\t\ttoken : handleToken,\n\t\t\t\t\t\tdetached : false,\n\t\t\t\t\t\twebrtcStuff : {\n\t\t\t\t\t\t\tstarted : false,\n\t\t\t\t\t\t\tmyStream : null,\n\t\t\t\t\t\t\tstreamExternal : false,\n\t\t\t\t\t\t\tmySdp : null,\n\t\t\t\t\t\t\tmediaConstraints : null,\n\t\t\t\t\t\t\tpc : null,\n\t\t\t\t\t\t\tdataChannelOptions: callbacks.dataChannelOptions,\n\t\t\t\t\t\t\tdataChannel : {},\n\t\t\t\t\t\t\tdtmfSender : null,\n\t\t\t\t\t\t\ttrickle : true,\n\t\t\t\t\t\t\ticeDone : false,\n\t\t\t\t\t\t\tbitrate: {}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgetId : function() { return handleId; },\n\t\t\t\t\t\tgetPlugin : function() { return plugin; },\n\t\t\t\t\t\tgetVolume : function(mid, result) { return getVolume(handleId, mid, true, result); },\n\t\t\t\t\t\tgetRemoteVolume : function(mid, result) { return getVolume(handleId, mid, true, result); },\n\t\t\t\t\t\tgetLocalVolume : function(mid, result) { return getVolume(handleId, mid, false, result); },\n\t\t\t\t\t\tisAudioMuted : function(mid) { return isMuted(handleId, mid, false); },\n\t\t\t\t\t\tmuteAudio : function(mid) { return mute(handleId, mid, false, true); },\n\t\t\t\t\t\tunmuteAudio : function(mid) { return mute(handleId, mid, false, false); },\n\t\t\t\t\t\tisVideoMuted : function(mid) { return isMuted(handleId, mid, true); },\n\t\t\t\t\t\tmuteVideo : function(mid) { return mute(handleId, mid, true, true); },\n\t\t\t\t\t\tunmuteVideo : function(mid) { return mute(handleId, mid, true, false); },\n\t\t\t\t\t\tgetBitrate : function(mid) { return getBitrate(handleId, mid); },\n\t\t\t\t\t\tsetMaxBitrate : function(mid, bitrate) { return setBitrate(handleId, mid, bitrate); },\n\t\t\t\t\t\tsend : function(callbacks) { sendMessage(handleId, callbacks); },\n\t\t\t\t\t\tdata : function(callbacks) { sendData(handleId, callbacks); },\n\t\t\t\t\t\tdtmf : function(callbacks) { sendDtmf(handleId, callbacks); },\n\t\t\t\t\t\tconsentDialog : callbacks.consentDialog,\n\t\t\t\t\t\ticeState : callbacks.iceState,\n\t\t\t\t\t\tmediaState : callbacks.mediaState,\n\t\t\t\t\t\twebrtcState : callbacks.webrtcState,\n\t\t\t\t\t\tslowLink : callbacks.slowLink,\n\t\t\t\t\t\tonmessage : callbacks.onmessage,\n\t\t\t\t\t\tcreateOffer : function(callbacks) { prepareWebrtc(handleId, true, callbacks); },\n\t\t\t\t\t\tcreateAnswer : function(callbacks) { prepareWebrtc(handleId, false, callbacks); },\n\t\t\t\t\t\thandleRemoteJsep : function(callbacks) { prepareWebrtcPeer(handleId, callbacks); },\n\t\t\t\t\t\treplaceTracks : function(callbacks) { replaceTracks(handleId, callbacks); },\n\t\t\t\t\t\tgetLocalTracks : function() { return getLocalTracks(handleId); },\n\t\t\t\t\t\tgetRemoteTracks : function() { return getRemoteTracks(handleId); },\n\t\t\t\t\t\tonlocaltrack : callbacks.onlocaltrack,\n\t\t\t\t\t\tonremotetrack : callbacks.onremotetrack,\n\t\t\t\t\t\tondata : callbacks.ondata,\n\t\t\t\t\t\tondataopen : callbacks.ondataopen,\n\t\t\t\t\t\toncleanup : callbacks.oncleanup,\n\t\t\t\t\t\tondetached : callbacks.ondetached,\n\t\t\t\t\t\thangup : function(sendRequest) { cleanupWebrtc(handleId, sendRequest === true); },\n\t\t\t\t\t\tdetach : function(callbacks) { destroyHandle(handleId, callbacks); }\n\t\t\t\t\t}\n\t\t\t\tpluginHandles[handleId] = pluginHandle;\n\t\t\t\tcallbacks.success(pluginHandle);\n\t\t\t},\n\t\t\terror: function(textStatus, errorThrown) {\n\t\t\t\tJanus.error(textStatus + \":\", errorThrown);\t// FIXME\n\t\t\t\tif(errorThrown === \"\")\n\t\t\t\t\tcallbacks.error(textStatus + \": Is the server down?\");\n\t\t\t\telse\n\t\t\t\t\tcallbacks.error(textStatus + \": \" + errorThrown);\n\t\t\t}\n\t\t});\n\t}\n\n\t// Private method to send a message\n\tfunction sendMessage(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tif(!connected) {\n\t\t\tJanus.warn(\"Is the server down? (connected=false)\");\n\t\t\tcallbacks.error(\"Is the server down? (connected=false)\");\n\t\t\treturn;\n\t\t}\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tcallbacks.error(\"Invalid handle\");\n\t\t\treturn;\n\t\t}\n\t\tlet message = callbacks.message;\n\t\tlet jsep = callbacks.jsep;\n\t\tlet transaction = Janus.randomString(12);\n\t\tlet request = { \"janus\": \"message\", \"body\": message, \"transaction\": transaction };\n\t\tif(pluginHandle.token)\n\t\t\trequest[\"token\"] = pluginHandle.token;\n\t\tif(apisecret)\n\t\t\trequest[\"apisecret\"] = apisecret;\n\t\tif(jsep) {\n\t\t\trequest.jsep = {\n\t\t\t\ttype: jsep.type,\n\t\t\t\tsdp: jsep.sdp\n\t\t\t};\n\t\t\tif(jsep.e2ee)\n\t\t\t\trequest.jsep.e2ee = true;\n\t\t\tif(jsep.rid_order === \"hml\" || jsep.rid_order === \"lmh\")\n\t\t\t\trequest.jsep.rid_order = jsep.rid_order;\n\t\t\tif(jsep.force_relay)\n\t\t\t\trequest.jsep.force_relay = true;\n\t\t}\n\t\tJanus.debug(\"Sending message to plugin (handle=\" + handleId + \"):\");\n\t\tJanus.debug(request);\n\t\tif(websockets) {\n\t\t\trequest[\"session_id\"] = sessionId;\n\t\t\trequest[\"handle_id\"] = handleId;\n\t\t\ttransactions[transaction] = function(json) {\n\t\t\t\tJanus.debug(\"Message sent!\");\n\t\t\t\tJanus.debug(json);\n\t\t\t\tif(json[\"janus\"] === \"success\") {\n\t\t\t\t\t// We got a success, must have been a synchronous transaction\n\t\t\t\t\tlet plugindata = json[\"plugindata\"];\n\t\t\t\t\tif(!plugindata) {\n\t\t\t\t\t\tJanus.warn(\"Request succeeded, but missing plugindata...\");\n\t\t\t\t\t\tcallbacks.success();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tJanus.log(\"Synchronous transaction successful (\" + plugindata[\"plugin\"] + \")\");\n\t\t\t\t\tlet data = plugindata[\"data\"];\n\t\t\t\t\tJanus.debug(data);\n\t\t\t\t\tcallbacks.success(data);\n\t\t\t\t\treturn;\n\t\t\t\t} else if(json[\"janus\"] !== \"ack\") {\n\t\t\t\t\t// Not a success and not an ack, must be an error\n\t\t\t\t\tif(json[\"error\"]) {\n\t\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t\t\tcallbacks.error(json[\"error\"].code + \" \" + json[\"error\"].reason);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tJanus.error(\"Unknown error\");\t// FIXME\n\t\t\t\t\t\tcallbacks.error(\"Unknown error\");\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// If we got here, the plugin decided to handle the request asynchronously\n\t\t\t\tcallbacks.success();\n\t\t\t};\n\t\t\tws.send(JSON.stringify(request));\n\t\t\treturn;\n\t\t}\n\t\tJanus.httpAPICall(server + \"/\" + sessionId + \"/\" + handleId, {\n\t\t\tverb: 'POST',\n\t\t\twithCredentials: withCredentials,\n\t\t\tbody: request,\n\t\t\tsuccess: function(json) {\n\t\t\t\tJanus.debug(\"Message sent!\");\n\t\t\t\tJanus.debug(json);\n\t\t\t\tif(json[\"janus\"] === \"success\") {\n\t\t\t\t\t// We got a success, must have been a synchronous transaction\n\t\t\t\t\tlet plugindata = json[\"plugindata\"];\n\t\t\t\t\tif(!plugindata) {\n\t\t\t\t\t\tJanus.warn(\"Request succeeded, but missing plugindata...\");\n\t\t\t\t\t\tcallbacks.success();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tJanus.log(\"Synchronous transaction successful (\" + plugindata[\"plugin\"] + \")\");\n\t\t\t\t\tlet data = plugindata[\"data\"];\n\t\t\t\t\tJanus.debug(data);\n\t\t\t\t\tcallbacks.success(data);\n\t\t\t\t\treturn;\n\t\t\t\t} else if(json[\"janus\"] !== \"ack\") {\n\t\t\t\t\t// Not a success and not an ack, must be an error\n\t\t\t\t\tif(json[\"error\"]) {\n\t\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t\t\tcallbacks.error(json[\"error\"].code + \" \" + json[\"error\"].reason);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tJanus.error(\"Unknown error\");\t// FIXME\n\t\t\t\t\t\tcallbacks.error(\"Unknown error\");\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// If we got here, the plugin decided to handle the request asynchronously\n\t\t\t\tcallbacks.success();\n\t\t\t},\n\t\t\terror: function(textStatus, errorThrown) {\n\t\t\t\tJanus.error(textStatus + \":\", errorThrown);\t// FIXME\n\t\t\t\tcallbacks.error(textStatus + \": \" + errorThrown);\n\t\t\t}\n\t\t});\n\t}\n\n\t// Private method to send a trickle candidate\n\tfunction sendTrickleCandidate(handleId, candidate) {\n\t\tif(!connected) {\n\t\t\tJanus.warn(\"Is the server down? (connected=false)\");\n\t\t\treturn;\n\t\t}\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\treturn;\n\t\t}\n\t\tlet request = { \"janus\": \"trickle\", \"candidate\": candidate, \"transaction\": Janus.randomString(12) };\n\t\tif(pluginHandle.token)\n\t\t\trequest[\"token\"] = pluginHandle.token;\n\t\tif(apisecret)\n\t\t\trequest[\"apisecret\"] = apisecret;\n\t\tJanus.vdebug(\"Sending trickle candidate (handle=\" + handleId + \"):\");\n\t\tJanus.vdebug(request);\n\t\tif(websockets) {\n\t\t\trequest[\"session_id\"] = sessionId;\n\t\t\trequest[\"handle_id\"] = handleId;\n\t\t\tws.send(JSON.stringify(request));\n\t\t\treturn;\n\t\t}\n\t\tJanus.httpAPICall(server + \"/\" + sessionId + \"/\" + handleId, {\n\t\t\tverb: 'POST',\n\t\t\twithCredentials: withCredentials,\n\t\t\tbody: request,\n\t\t\tsuccess: function(json) {\n\t\t\t\tJanus.vdebug(\"Candidate sent!\");\n\t\t\t\tJanus.vdebug(json);\n\t\t\t\tif(json[\"janus\"] !== \"ack\") {\n\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function(textStatus, errorThrown) {\n\t\t\t\tJanus.error(textStatus + \":\", errorThrown);\t// FIXME\n\t\t\t}\n\t\t});\n\t}\n\n\t// Private method to create a data channel\n\tfunction createDataChannel(handleId, dclabel, dcprotocol, incoming, pendingData) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\treturn;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.pc) {\n\t\t\tJanus.warn(\"Invalid PeerConnection\");\n\t\t\treturn;\n\t\t}\n\t\tlet onDataChannelMessage = function(event) {\n\t\t\tJanus.log('Received message on data channel:', event);\n\t\t\tlet label = event.target.label;\n\t\t\tpluginHandle.ondata(event.data, label);\n\t\t};\n\t\tlet onDataChannelStateChange = function(event) {\n\t\t\tJanus.log('Received state change on data channel:', event);\n\t\t\tlet label = event.target.label;\n\t\t\tlet protocol = event.target.protocol;\n\t\t\tlet dcState = config.dataChannel[label] ? config.dataChannel[label].readyState : \"null\";\n\t\t\tJanus.log('State change on <' + label + '> data channel: ' + dcState);\n\t\t\tif(dcState === 'open') {\n\t\t\t\t// Any pending messages to send?\n\t\t\t\tif(config.dataChannel[label].pending && config.dataChannel[label].pending.length > 0) {\n\t\t\t\t\tJanus.log(\"Sending pending messages on <\" + label + \">:\", config.dataChannel[label].pending.length);\n\t\t\t\t\tfor(let data of config.dataChannel[label].pending) {\n\t\t\t\t\t\tJanus.log(\"Sending data on data channel <\" + label + \">\");\n\t\t\t\t\t\tJanus.debug(data);\n\t\t\t\t\t\tconfig.dataChannel[label].send(data);\n\t\t\t\t\t}\n\t\t\t\t\tconfig.dataChannel[label].pending = [];\n\t\t\t\t}\n\t\t\t\t// Notify the open data channel\n\t\t\t\tpluginHandle.ondataopen(label, protocol);\n\t\t\t}\n\t\t};\n\t\tlet onDataChannelError = function(error) {\n\t\t\tJanus.error('Got error on data channel:', error);\n\t\t\t// TODO\n\t\t};\n\t\tif(!incoming) {\n\t\t\t// FIXME Add options (ordered, maxRetransmits, etc.)\n\t\t\tlet dcoptions = config.dataChannelOptions;\n\t\t\tif(dcprotocol)\n\t\t\t\tdcoptions.protocol = dcprotocol;\n\t\t\tconfig.dataChannel[dclabel] = config.pc.createDataChannel(dclabel, dcoptions);\n\t\t} else {\n\t\t\t// The channel was created by Janus\n\t\t\tconfig.dataChannel[dclabel] = incoming;\n\t\t}\n\t\tconfig.dataChannel[dclabel].onmessage = onDataChannelMessage;\n\t\tconfig.dataChannel[dclabel].onopen = onDataChannelStateChange;\n\t\tconfig.dataChannel[dclabel].onclose = onDataChannelStateChange;\n\t\tconfig.dataChannel[dclabel].onerror = onDataChannelError;\n\t\tconfig.dataChannel[dclabel].pending = [];\n\t\tif(pendingData)\n\t\t\tconfig.dataChannel[dclabel].pending.push(pendingData);\n\t}\n\n\t// Private method to send a data channel message\n\tfunction sendData(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tcallbacks.error(\"Invalid handle\");\n\t\t\treturn;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tlet data = callbacks.text || callbacks.data;\n\t\tif(!data) {\n\t\t\tJanus.warn(\"Invalid data\");\n\t\t\tcallbacks.error(\"Invalid data\");\n\t\t\treturn;\n\t\t}\n\t\tlet label = callbacks.label ? callbacks.label : Janus.dataChanDefaultLabel;\n\t\tif(!config.dataChannel[label]) {\n\t\t\t// Create new data channel and wait for it to open\n\t\t\tcreateDataChannel(handleId, label, callbacks.protocol, false, data, callbacks.protocol);\n\t\t\tcallbacks.success();\n\t\t\treturn;\n\t\t}\n\t\tif(config.dataChannel[label].readyState !== \"open\") {\n\t\t\tconfig.dataChannel[label].pending.push(data);\n\t\t\tcallbacks.success();\n\t\t\treturn;\n\t\t}\n\t\tJanus.log(\"Sending data on data channel <\" + label + \">\");\n\t\tJanus.debug(data);\n\t\tconfig.dataChannel[label].send(data);\n\t\tcallbacks.success();\n\t}\n\n\t// Private method to send a DTMF tone\n\tfunction sendDtmf(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tcallbacks.error(\"Invalid handle\");\n\t\t\treturn;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.dtmfSender) {\n\t\t\t// Create the DTMF sender the proper way, if possible\n\t\t\tif(config.pc) {\n\t\t\t\tlet senders = config.pc.getSenders();\n\t\t\t\tlet audioSender = senders.find(function(sender) {\n\t\t\t\t\treturn sender.track && sender.track.kind === 'audio';\n\t\t\t\t});\n\t\t\t\tif(!audioSender) {\n\t\t\t\t\tJanus.warn(\"Invalid DTMF configuration (no audio track)\");\n\t\t\t\t\tcallbacks.error(\"Invalid DTMF configuration (no audio track)\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconfig.dtmfSender = audioSender.dtmf;\n\t\t\t\tif(config.dtmfSender) {\n\t\t\t\t\tJanus.log(\"Created DTMF Sender\");\n\t\t\t\t\tconfig.dtmfSender.ontonechange = function(tone) { Janus.debug(\"Sent DTMF tone: \" + tone.tone); };\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(!config.dtmfSender) {\n\t\t\t\tJanus.warn(\"Invalid DTMF configuration\");\n\t\t\t\tcallbacks.error(\"Invalid DTMF configuration\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tlet dtmf = callbacks.dtmf;\n\t\tif(!dtmf) {\n\t\t\tJanus.warn(\"Invalid DTMF parameters\");\n\t\t\tcallbacks.error(\"Invalid DTMF parameters\");\n\t\t\treturn;\n\t\t}\n\t\tlet tones = dtmf.tones;\n\t\tif(!tones) {\n\t\t\tJanus.warn(\"Invalid DTMF string\");\n\t\t\tcallbacks.error(\"Invalid DTMF string\");\n\t\t\treturn;\n\t\t}\n\t\tlet duration = (typeof dtmf.duration === 'number') ? dtmf.duration : 500; // We choose 500ms as the default duration for a tone\n\t\tlet gap = (typeof dtmf.gap === 'number') ? dtmf.gap : 50; // We choose 50ms as the default gap between tones\n\t\tJanus.debug(\"Sending DTMF string \" + tones + \" (duration \" + duration + \"ms, gap \" + gap + \"ms)\");\n\t\tconfig.dtmfSender.insertDTMF(tones, duration, gap);\n\t\tcallbacks.success();\n\t}\n\n\t// Private method to destroy a plugin handle\n\tfunction destroyHandle(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tlet noRequest = (callbacks.noRequest === true);\n\t\tJanus.log(\"Destroying handle \" + handleId + \" (only-locally=\" + noRequest + \")\");\n\t\tcleanupWebrtc(handleId);\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || pluginHandle.detached) {\n\t\t\t// Plugin was already detached by Janus, calling detach again will return a handle not found error, so just exit here\n\t\t\tdelete pluginHandles[handleId];\n\t\t\tcallbacks.success();\n\t\t\treturn;\n\t\t}\n\t\tpluginHandle.detached = true;\n\t\tif(noRequest) {\n\t\t\t// We're only removing the handle locally\n\t\t\tdelete pluginHandles[handleId];\n\t\t\tcallbacks.success();\n\t\t\treturn;\n\t\t}\n\t\tif(!connected) {\n\t\t\tJanus.warn(\"Is the server down? (connected=false)\");\n\t\t\tcallbacks.error(\"Is the server down? (connected=false)\");\n\t\t\treturn;\n\t\t}\n\t\tlet request = { \"janus\": \"detach\", \"transaction\": Janus.randomString(12) };\n\t\tif(pluginHandle.token)\n\t\t\trequest[\"token\"] = pluginHandle.token;\n\t\tif(apisecret)\n\t\t\trequest[\"apisecret\"] = apisecret;\n\t\tif(websockets) {\n\t\t\trequest[\"session_id\"] = sessionId;\n\t\t\trequest[\"handle_id\"] = handleId;\n\t\t\tws.send(JSON.stringify(request));\n\t\t\tdelete pluginHandles[handleId];\n\t\t\tcallbacks.success();\n\t\t\treturn;\n\t\t}\n\t\tJanus.httpAPICall(server + \"/\" + sessionId + \"/\" + handleId, {\n\t\t\tverb: 'POST',\n\t\t\twithCredentials: withCredentials,\n\t\t\tbody: request,\n\t\t\tsuccess: function(json) {\n\t\t\t\tJanus.log(\"Destroyed handle:\");\n\t\t\t\tJanus.debug(json);\n\t\t\t\tif(json[\"janus\"] !== \"success\") {\n\t\t\t\t\tJanus.error(\"Ooops: \" + json[\"error\"].code + \" \" + json[\"error\"].reason);\t// FIXME\n\t\t\t\t}\n\t\t\t\tdelete pluginHandles[handleId];\n\t\t\t\tcallbacks.success();\n\t\t\t},\n\t\t\terror: function(textStatus, errorThrown) {\n\t\t\t\tJanus.error(textStatus + \":\", errorThrown);\t// FIXME\n\t\t\t\t// We cleanup anyway\n\t\t\t\tdelete pluginHandles[handleId];\n\t\t\t\tcallbacks.success();\n\t\t\t}\n\t\t});\n\t}\n\n\t// WebRTC stuff\n\t// Helper function to create a new PeerConnection, if we need one\n\tfunction createPeerconnectionIfNeeded(handleId, callbacks) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tthrow \"Invalid handle\";\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(config.pc) {\n\t\t\t// Nothing to do, we have a PeerConnection already\n\t\t\treturn;\n\t\t}\n\t\tlet pc_config = {\n\t\t\ticeServers: iceServers,\n\t\t\ticeTransportPolicy: iceTransportPolicy,\n\t\t\tbundlePolicy: bundlePolicy\n\t\t};\n\t\tpc_config.sdpSemantics = 'unified-plan';\n\t\t// Check if a sender or receiver transform has been provided\n\t\tlet insertableStreams = false;\n\t\tif(callbacks.tracks) {\n\t\t\tfor(let track of callbacks.tracks) {\n\t\t\t\tif(track.transforms && (track.transforms.sender || track.transforms.receiver)) {\n\t\t\t\t\tinsertableStreams = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(RTCRtpSender && (RTCRtpSender.prototype.createEncodedStreams ||\n\t\t\t\t(RTCRtpSender.prototype.createEncodedAudioStreams &&\n\t\t\t\tRTCRtpSender.prototype.createEncodedVideoStreams)) && insertableStreams) {\n\t\t\tconfig.insertableStreams = true;\n\t\t\tpc_config.forceEncodedAudioInsertableStreams = true;\n\t\t\tpc_config.forceEncodedVideoInsertableStreams = true;\n\t\t\tpc_config.encodedInsertableStreams = true;\n\t\t}\n\t\tJanus.log('Creating PeerConnection');\n\t\tconfig.pc = new RTCPeerConnection(pc_config);\n\t\tJanus.debug(config.pc);\n\t\tif(config.pc.getStats) {\t// FIXME\n\t\t\tconfig.volume = {};\n\t\t\tconfig.bitrate.value = '0 kbits/sec';\n\t\t}\n\t\tJanus.log('Preparing local SDP and gathering candidates (trickle=' + config.trickle + ')');\n\t\tconfig.pc.oniceconnectionstatechange = function() {\n\t\t\tif(config.pc)\n\t\t\t\tpluginHandle.iceState(config.pc.iceConnectionState);\n\t\t};\n\t\tconfig.pc.onicecandidate = function(event) {\n\t\t\tif(!event.candidate || (event.candidate.candidate && event.candidate.candidate.indexOf('endOfCandidates') > 0)) {\n\t\t\t\tJanus.log('End of candidates.');\n\t\t\t\tconfig.iceDone = true;\n\t\t\t\tif(config.trickle === true) {\n\t\t\t\t\t// Notify end of candidates\n\t\t\t\t\tsendTrickleCandidate(handleId, { completed : true });\n\t\t\t\t} else {\n\t\t\t\t\t// No trickle, time to send the complete SDP (including all candidates)\n\t\t\t\t\tsendSDP(handleId, callbacks);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// JSON.stringify doesn't work on some WebRTC objects anymore\n\t\t\t\t// See https://code.google.com/p/chromium/issues/detail?id=467366\n\t\t\t\tlet candidate = {\n\t\t\t\t\tcandidate: event.candidate.candidate,\n\t\t\t\t\tsdpMid: event.candidate.sdpMid,\n\t\t\t\t\tsdpMLineIndex: event.candidate.sdpMLineIndex\n\t\t\t\t};\n\t\t\t\tif(config.trickle === true) {\n\t\t\t\t\t// Send candidate\n\t\t\t\t\tsendTrickleCandidate(handleId, candidate);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tconfig.pc.ontrack = function(event) {\n\t\t\tJanus.log('Handling Remote Track', event);\n\t\t\tif(!event.streams)\n\t\t\t\treturn;\n\t\t\tif(!event.track)\n\t\t\t\treturn;\n\t\t\t// Notify about the new track event\n\t\t\tlet mid = event.transceiver ? event.transceiver.mid : event.track.id;\n\t\t\ttry {\n\t\t\t\tpluginHandle.onremotetrack(event.track, mid, true);\n\t\t\t} catch(e) {\n\t\t\t\tJanus.error(\"Error calling onremotetrack\", e);\n\t\t\t}\n\t\t\tif(event.track.onended)\n\t\t\t\treturn;\n\t\t\tlet trackMutedTimeoutId = null;\n\t\t\tJanus.log('Adding onended callback to track:', event.track);\n\t\t\tevent.track.onended = function(ev) {\n\t\t\t\tJanus.log('Remote track removed:', ev);\n\t\t\t\tclearTimeout(trackMutedTimeoutId);\n\t\t\t\t// Notify the application\n\t\t\t\tlet transceivers = config.pc ? config.pc.getTransceivers() : null;\n\t\t\t\tlet transceiver = transceivers ? transceivers.find(\n\t\t\t\t\tt => t.receiver.track === ev.target) : null;\n\t\t\t\tlet mid = transceiver ? transceiver.mid : ev.target.id;\n\t\t\t\ttry {\n\t\t\t\t\tpluginHandle.onremotetrack(ev.target, mid, false);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tJanus.error(\"Error calling onremotetrack on removal\", e);\n\t\t\t\t}\n\t\t\t};\n\t\t\tevent.track.onmute = function(ev) {\n\t\t\t\tJanus.log('Remote track muted:', ev);\n\t\t\t\tif(!trackMutedTimeoutId) {\n\t\t\t\t\ttrackMutedTimeoutId = setTimeout(function() {\n\t\t\t\t\t\tJanus.log('Removing remote track');\n\t\t\t\t\t\t// Notify the application the track is gone\n\t\t\t\t\t\tlet transceivers = config.pc ? config.pc.getTransceivers() : null;\n\t\t\t\t\t\tlet transceiver = transceivers ? transceivers.find(\n\t\t\t\t\t\t\tt => t.receiver.track === ev.target) : null;\n\t\t\t\t\t\tlet mid = transceiver ? transceiver.mid : ev.target.id;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tpluginHandle.onremotetrack(ev.target, mid, false);\n\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\tJanus.error(\"Error calling onremotetrack on mute\", e);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttrackMutedTimeoutId = null;\n\t\t\t\t\t// Chrome seems to raise mute events only at multiples of 834ms;\n\t\t\t\t\t// we set the timeout to three times this value (rounded to 840ms)\n\t\t\t\t\t}, 3 * 840);\n\t\t\t\t}\n\t\t\t};\n\t\t\tevent.track.onunmute = function(ev) {\n\t\t\t\tJanus.log('Remote track flowing again:', ev);\n\t\t\t\tif(trackMutedTimeoutId != null) {\n\t\t\t\t\tclearTimeout(trackMutedTimeoutId);\n\t\t\t\t\ttrackMutedTimeoutId = null;\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Notify the application the track is back\n\t\t\t\t\t\tlet transceivers = config.pc ? config.pc.getTransceivers() : null;\n\t\t\t\t\t\tlet transceiver = transceivers ? transceivers.find(\n\t\t\t\t\t\t\tt => t.receiver.track === ev.target) : null;\n\t\t\t\t\t\tlet mid = transceiver ? transceiver.mid : ev.target.id;\n\t\t\t\t\t\tpluginHandle.onremotetrack(ev.target, mid, true);\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\tJanus.error(\"Error calling onremotetrack on unmute\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t};\n\t}\n\n\t// Helper function used when creating either an offer or answer: it\n\t// prepares what needs to be prepared, including creating a new\n\t// PeerConnection (if needed) and updating the tracks configuration,\n\t// before invoking the function to actually generate the offer/answer\n\tasync function prepareWebrtc(handleId, offer, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : webrtcError;\n\t\tlet jsep = callbacks.jsep;\n\t\tif(offer && jsep) {\n\t\t\tJanus.error(\"Provided a JSEP to a createOffer\");\n\t\t\tcallbacks.error(\"Provided a JSEP to a createOffer\");\n\t\t\treturn;\n\t\t} else if(!offer && (!jsep || !jsep.type || !jsep.sdp)) {\n\t\t\tJanus.error(\"A valid JSEP is required for createAnswer\");\n\t\t\tcallbacks.error(\"A valid JSEP is required for createAnswer\");\n\t\t\treturn;\n\t\t}\n\t\t// If the deprecated media was provided instead of tracks, translate it\n\t\tif(callbacks.media && !callbacks.tracks) {\n\t\t\tcallbacks.tracks = Janus.mediaToTracks(callbacks.media);\n\t\t\tif(callbacks.simulcast === true || callbacks.simulcast2 === true || callbacks.svc) {\n\t\t\t\t// Find the video track and add simulcast/SVC info there\n\t\t\t\tfor(let track of callbacks.tracks) {\n\t\t\t\t\tif(track.type === 'video') {\n\t\t\t\t\t\tif(callbacks.simulcast === true || callbacks.simulcast2 === true)\n\t\t\t\t\t\t\ttrack.simulcast = true;\n\t\t\t\t\t\telse if(callbacks.svc)\n\t\t\t\t\t\t\ttrack.svc = callbacks.svc;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tJanus.warn('Deprecated media object passed, use tracks instead. Automatically translated to:', callbacks.tracks);\n\t\t}\n\t\t// Check that callbacks.array is a valid array\n\t\tif(callbacks.tracks && !Array.isArray(callbacks.tracks)) {\n\t\t\tJanus.error(\"Tracks must be an array\");\n\t\t\tcallbacks.error(\"Tracks must be an array\");\n\t\t\treturn;\n\t\t}\n\t\t// Get the plugin handle\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tcallbacks.error(\"Invalid handle\");\n\t\t\treturn;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tconfig.trickle = isTrickleEnabled(callbacks.trickle);\n\t\ttry {\n\t\t\t// Create a PeerConnection, if needed\n\t\t\tcreatePeerconnectionIfNeeded(handleId, callbacks);\n\t\t\tif(offer) {\n\t\t\t\t// Capture devices and setup tracks, if needed\n\t\t\t\tawait captureDevices(handleId, callbacks);\n\t\t\t}\n\t\t\t// Create offer or answer now (depending on the context)\n\t\t\tif(!jsep) {\n\t\t\t\tlet offer = await createOffer(handleId, callbacks);\n\t\t\t\tcallbacks.success(offer);\n\t\t\t} else {\n\t\t\t\tawait config.pc.setRemoteDescription(jsep);\n\t\t\t\tJanus.log(\"Remote description accepted!\");\n\t\t\t\tconfig.remoteSdp = jsep.sdp;\n\t\t\t\t// Any trickle candidate we cached?\n\t\t\t\tif(config.candidates && config.candidates.length > 0) {\n\t\t\t\t\tfor(let i=0; i<config.candidates.length; i++) {\n\t\t\t\t\t\tlet candidate = config.candidates[i];\n\t\t\t\t\t\tJanus.debug(\"Adding remote candidate:\", candidate);\n\t\t\t\t\t\tif(!candidate || candidate.completed === true) {\n\t\t\t\t\t\t\t// end-of-candidates\n\t\t\t\t\t\t\tconfig.pc.addIceCandidate(Janus.endOfCandidates);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// New candidate\n\t\t\t\t\t\t\tconfig.pc.addIceCandidate(candidate);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconfig.candidates = [];\n\t\t\t\t}\n\t\t\t\t// Capture devices and setup tracks, if needed\n\t\t\t\tawait captureDevices(handleId, callbacks);\n\t\t\t\t// Create the answer now\n\t\t\t\tlet answer = await createAnswer(handleId, callbacks);\n\t\t\t\tcallbacks.success(answer);\n\t\t\t}\n\t\t} catch(err) {\n\t\t\tJanus.error(err);\n\t\t\tcallbacks.error(err);\n\t\t}\n\t}\n\n\tfunction prepareWebrtcPeer(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : webrtcError;\n\t\tcallbacks.customizeSdp = (typeof callbacks.customizeSdp == \"function\") ? callbacks.customizeSdp : Janus.noop;\n\t\tlet jsep = callbacks.jsep;\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tcallbacks.error(\"Invalid handle\");\n\t\t\treturn;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(jsep) {\n\t\t\tif(!config.pc) {\n\t\t\t\tJanus.warn(\"Wait, no PeerConnection?? if this is an answer, use createAnswer and not handleRemoteJsep\");\n\t\t\t\tcallbacks.error(\"No PeerConnection: if this is an answer, use createAnswer and not handleRemoteJsep\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcallbacks.customizeSdp(jsep);\n\t\t\tconfig.pc.setRemoteDescription(jsep)\n\t\t\t\t.then(function() {\n\t\t\t\t\tJanus.log(\"Remote description accepted!\");\n\t\t\t\t\tconfig.remoteSdp = jsep.sdp;\n\t\t\t\t\t// Any trickle candidate we cached?\n\t\t\t\t\tif(config.candidates && config.candidates.length > 0) {\n\t\t\t\t\t\tfor(let i=0; i<config.candidates.length; i++) {\n\t\t\t\t\t\t\tlet candidate = config.candidates[i];\n\t\t\t\t\t\t\tJanus.debug(\"Adding remote candidate:\", candidate);\n\t\t\t\t\t\t\tif(!candidate || candidate.completed === true) {\n\t\t\t\t\t\t\t\t// end-of-candidates\n\t\t\t\t\t\t\t\tconfig.pc.addIceCandidate(Janus.endOfCandidates);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// New candidate\n\t\t\t\t\t\t\t\tconfig.pc.addIceCandidate(candidate);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconfig.candidates = [];\n\t\t\t\t\t}\n\t\t\t\t\t// Done\n\t\t\t\t\tcallbacks.success();\n\t\t\t\t}, callbacks.error);\n\t\t} else {\n\t\t\tcallbacks.error(\"Invalid JSEP\");\n\t\t}\n\t}\n\n\tasync function createOffer(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.customizeSdp = (typeof callbacks.customizeSdp == \"function\") ? callbacks.customizeSdp : Janus.noop;\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tthrow \"Invalid handle\";\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tJanus.log(\"Creating offer (iceDone=\" + config.iceDone + \")\");\n\t\t// https://code.google.com/p/webrtc/issues/detail?id=3508\n\t\tlet mediaConstraints = {};\n\t\tlet iceRestart = (callbacks.iceRestart === true);\n\t\t// If we need an ICE restart, set the related constraint\n\t\tif(iceRestart)\n\t\t\tmediaConstraints.iceRestart = true;\n\t\tJanus.debug(mediaConstraints);\n\t\tlet offer = await config.pc.createOffer(mediaConstraints);\n\t\tJanus.debug(offer);\n\t\t// JSON.stringify doesn't work on some WebRTC objects anymore\n\t\t// See https://code.google.com/p/chromium/issues/detail?id=467366\n\t\tlet jsep = {\n\t\t\ttype: 'offer',\n\t\t\tsdp: offer.sdp\n\t\t};\n\t\tcallbacks.customizeSdp(jsep);\n\t\toffer.sdp = jsep.sdp;\n\t\tJanus.log(\"Setting local description\");\n\t\tconfig.mySdp = {\n\t\t\ttype: 'offer',\n\t\t\tsdp: offer.sdp\n\t\t};\n\t\tawait config.pc.setLocalDescription(offer);\n\t\tconfig.mediaConstraints = mediaConstraints;\n\t\tif(!config.iceDone && !config.trickle) {\n\t\t\t// FIXME Don't do anything until we have all candidates\n\t\t\tJanus.log(\"Waiting for all candidates...\");\n\t\t\treturn null;\n\t\t}\n\t\t// If transforms are present, notify Janus that the media is end-to-end encrypted\n\t\tif(config.insertableStreams)\n\t\t\toffer.e2ee = true;\n\t\treturn offer;\n\t}\n\n\tasync function createAnswer(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.customizeSdp = (typeof callbacks.customizeSdp == \"function\") ? callbacks.customizeSdp : Janus.noop;\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tthrow \"Invalid handle\";\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tJanus.log(\"Creating answer (iceDone=\" + config.iceDone + \")\");\n\t\tlet answer = await config.pc.createAnswer();\n\t\tJanus.debug(answer);\n\t\t// JSON.stringify doesn't work on some WebRTC objects anymore\n\t\t// See https://code.google.com/p/chromium/issues/detail?id=467366\n\t\tlet jsep = {\n\t\t\ttype: 'answer',\n\t\t\tsdp: answer.sdp\n\t\t};\n\t\tcallbacks.customizeSdp(jsep);\n\t\tanswer.sdp = jsep.sdp;\n\t\tJanus.log(\"Setting local description\");\n\t\tconfig.mySdp = {\n\t\t\ttype: 'answer',\n\t\t\tsdp: answer.sdp\n\t\t};\n\t\tawait config.pc.setLocalDescription(answer);\n\t\tif(!config.iceDone && !config.trickle) {\n\t\t\t// FIXME Don't do anything until we have all candidates\n\t\t\tJanus.log(\"Waiting for all candidates...\");\n\t\t\treturn null;\n\t\t}\n\t\t// If transforms are present, notify Janus that the media is end-to-end encrypted\n\t\tif(config.insertableStreams)\n\t\t\tanswer.e2ee = true;\n\t\treturn answer;\n\t}\n\n\tfunction sendSDP(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == \"function\") ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == \"function\") ? callbacks.error : Janus.noop;\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle, not sending anything\");\n\t\t\treturn;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tJanus.log(\"Sending offer/answer SDP...\");\n\t\tif(!config.mySdp) {\n\t\t\tJanus.warn(\"Local SDP instance is invalid, not sending anything...\");\n\t\t\treturn;\n\t\t}\n\t\tconfig.mySdp = {\n\t\t\ttype: config.pc.localDescription.type,\n\t\t\tsdp: config.pc.localDescription.sdp\n\t\t};\n\t\tif(config.trickle === false)\n\t\t\tconfig.mySdp[\"trickle\"] = false;\n\t\tJanus.debug(callbacks);\n\t\tconfig.sdpSent = true;\n\t\tcallbacks.success(config.mySdp);\n\t}\n\n\tasync function replaceTracks(handleId, callbacks) {\n\t\tcallbacks = callbacks || {};\n\t\tcallbacks.success = (typeof callbacks.success == 'function') ? callbacks.success : Janus.noop;\n\t\tcallbacks.error = (typeof callbacks.error == 'function') ? callbacks.error : Janus.noop;\n\t\t// Check that callbacks.array is a valid array\n\t\tif(callbacks.tracks && !Array.isArray(callbacks.tracks)) {\n\t\t\tJanus.error('Tracks must be an array');\n\t\t\tcallbacks.error('Tracks must be an array');\n\t\t\treturn;\n\t\t}\n\t\t// Add the replace:true if it's missing\n\t\tfor(let track of callbacks.tracks) {\n\t\t\tif(track.add || (!track.replace && !track.remove))\n\t\t\t\ttrack.replace = true;\n\t\t}\n\t\ttry {\n\t\t\tawait captureDevices(handleId, callbacks);\n\t\t\tcallbacks.success();\n\t\t} catch(err) {\n\t\t\tJanus.error(err);\n\t\t\tcallbacks.error(err);\n\t\t}\n\t}\n\n\tasync function captureDevices(handleId, callbacks) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn('Invalid handle, not sending anything');\n\t\t\tthrow 'Invalid handle';\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.pc) {\n\t\t\tJanus.warn('Invalid PeerConnection');\n\t\t\tthrow 'Invalid PeerConnection';\n\t\t}\n\t\tlet tracks = callbacks.tracks;\n\t\tif(!tracks || !Array.isArray(tracks) || tracks.length === 0) {\n\t\t\t// Nothing to do\n\t\t\treturn;\n\t\t}\n\t\tlet openedConsentDialog = false;\n\t\t// Check if we can/should group getUserMedia calls\n\t\tlet groups = {};\n\t\tfor(let track of tracks) {\n\t\t\tdelete track.gumGroup;\n\t\t\tif(!track.type || !['audio', 'video'].includes(track.type))\n\t\t\t\tcontinue;\n\t\t\tif(!track.capture || track.capture instanceof MediaStreamTrack)\n\t\t\t\tcontinue;\n\t\t\tlet group = track.group ? track.group : 'default';\n\t\t\tif(!groups[group])\n\t\t\t\tgroups[group] = {};\n\t\t\tif(groups[group][track.type])\n\t\t\t\tcontinue;\n\t\t\ttrack.gumGroup = group;\n\t\t\tgroups[group][track.type] = track;\n\t\t}\n\t\tlet keys = Object.keys(groups);\n\t\tfor(let key of keys) {\n\t\t\tlet group = groups[key];\n\t\t\tif(!group.audio || !group.video) {\n\t\t\t\tif(group.audio)\n\t\t\t\t\tdelete group.audio.gumGroup;\n\t\t\t\tif(group.video)\n\t\t\t\t\tdelete group.video.gumGroup;\n\t\t\t\tdelete groups[key];\n\t\t\t}\n\t\t}\n\t\tlet answer = (callbacks.jsep ? true : false);\n\t\tfor(let track of tracks) {\n\t\t\tif(!track.type) {\n\t\t\t\tJanus.warn('Missing track type:', track);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif(track.type === 'data') {\n\t\t\t\t// Easy enough: create a datachannel if we don't have one already\n\t\t\t\tif(config.pc.ondatachannel) {\n\t\t\t\t\tJanus.warn('Data channel exists already, not creating another one');\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tJanus.log('Creating default data channel');\n\t\t\t\tcreateDataChannel(handleId, Janus.dataChanDefaultLabel, null, false);\n\t\t\t\tconfig.pc.ondatachannel = function(event) {\n\t\t\t\t\tJanus.log('Data channel created by Janus:', event);\n\t\t\t\t\tcreateDataChannel(handleId, event.channel.label, event.channel.protocol, event.channel);\n\t\t\t\t};\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif((typeof track.add === 'undefined' && track.add === null) &&\n\t\t\t\t\t(typeof track.remove === 'undefined' && track.remove === null) &&\n\t\t\t\t\t(typeof track.replace === 'undefined' && track.replace === null)) {\n\t\t\t\t// Let's default to 'add'\n\t\t\t\ttrack.add = true;\n\t\t\t}\n\t\t\tif((track.add && track.remove) || (track.add && track.remove && track.replace)) {\n\t\t\t\tJanus.warn('Conflicting actions for track, ignoring:', track);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif(track.add && track.replace) {\n\t\t\t\tJanus.warn('Both add and replace provided, falling back to replace:', track);\n\t\t\t\tdelete track.add;\n\t\t\t} else if(track.remove && track.replace) {\n\t\t\t\tJanus.warn('Both remove and replace provided, falling back to remove:', track);\n\t\t\t\tdelete track.replace;\n\t\t\t}\n\t\t\tlet kind = track.type;\n\t\t\tif(track.type === 'screen')\n\t\t\t\tkind = 'video';\t// FIXME\n\t\t\tlet transceiver = null, sender = null;\n\t\t\tif(track.mid) {\n\t\t\t\t// Search by mid\n\t\t\t\ttransceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.mid === track.mid && t.receiver.track.kind === kind));\n\t\t\t} else {\n\t\t\t\t// Find the first track of this type\n\t\t\t\ttransceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.receiver.track.kind === kind));\n\t\t\t}\n\t\t\tif(track.replace || track.remove) {\n\t\t\t\tif(!transceiver) {\n\t\t\t\t\tJanus.warn(\"Couldn't find a transceiver for track:\", track);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif(!transceiver.sender) {\n\t\t\t\t\tJanus.warn('No sender in the transceiver for track:', track);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tsender = transceiver.sender;\n\t\t\t}\n\t\t\tif(answer && !transceiver) {\n\t\t\t\ttransceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.receiver.track.kind === kind));\n\t\t\t\tif(!transceiver) {\n\t\t\t\t\tJanus.warn(\"Couldn't find a transceiver for track:\", track);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Capture the new track, if we need to\n\t\t\tlet nt = null, trackId = null;\n\t\t\tif(track.remove) {\n\t\t\t\tJanus.log('Removing track from PeerConnection', track);\n\t\t\t\ttrackId = sender.track ? sender.track.id : null;\n\t\t\t\tawait sender.replaceTrack(null);\n\t\t\t} else if(track.capture) {\n\t\t\t\tif(track.gumGroup && groups[track.gumGroup] && groups[track.gumGroup].stream) {\n\t\t\t\t\t// We did a getUserMedia before already\n\t\t\t\t\tlet stream = groups[track.gumGroup].stream;\n\t\t\t\t\tnt = (track.type === 'audio' ? stream.getAudioTracks()[0] : stream.getVideoTracks()[0]);\n\t\t\t\t\tdelete groups[track.gumGroup].stream;\n\t\t\t\t\tdelete groups[track.gumGroup];\n\t\t\t\t\tdelete track.gumGroup;\n\t\t\t\t} else if(track.capture instanceof MediaStreamTrack) {\n\t\t\t\t\t// An external track was provided, use that\n\t\t\t\t\tnt = track.capture;\n\t\t\t\t} else {\n\t\t\t\t\tif(!openedConsentDialog) {\n\t\t\t\t\t\topenedConsentDialog = true;\n\t\t\t\t\t\tpluginHandle.consentDialog(true);\n\t\t\t\t\t}\n\t\t\t\t\tlet constraints = Janus.trackConstraints(track), stream = null;\n\t\t\t\t\tif(track.type === 'audio' || track.type === 'video') {\n\t\t\t\t\t\t// Use getUserMedia: check if we need to group audio and video together\n\t\t\t\t\t\tif(track.gumGroup) {\n\t\t\t\t\t\t\tlet otherType = (track.type === 'audio' ? 'video' : 'audio');\n\t\t\t\t\t\t\tif(groups[track.gumGroup] && groups[track.gumGroup][otherType]) {\n\t\t\t\t\t\t\t\tlet otherTrack = groups[track.gumGroup][otherType];\n\t\t\t\t\t\t\t\tlet otherConstraints = Janus.trackConstraints(otherTrack);\n\t\t\t\t\t\t\t\tconstraints[otherType] = otherConstraints[otherType];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstream = await navigator.mediaDevices.getUserMedia(constraints);\n\t\t\t\t\t\tif(track.gumGroup && constraints.audio && constraints.video) {\n\t\t\t\t\t\t\t// We just performed a grouped getUserMedia, keep track of the\n\t\t\t\t\t\t\t// stream so that we can immediately assign the track later\n\t\t\t\t\t\t\tgroups[track.gumGroup].stream = stream;\n\t\t\t\t\t\t\tdelete track.gumGroup;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Use getDisplayMedia\n\t\t\t\t\t\tstream = await navigator.mediaDevices.getDisplayMedia(constraints);\n\t\t\t\t\t}\n\t\t\t\t\tnt = (track.type === 'audio' ? stream.getAudioTracks()[0] : stream.getVideoTracks()[0]);\n\t\t\t\t}\n\t\t\t\tif(track.replace) {\n\t\t\t\t\t// Replace the track\n\t\t\t\t\tawait sender.replaceTrack(nt);\n\t\t\t\t\t// Update the transceiver direction\n\t\t\t\t\tlet newDirection = 'sendrecv';\n\t\t\t\t\tif(track.recv === false || transceiver.direction === 'inactive' || transceiver.direction === 'sendonly')\n\t\t\t\t\t\tnewDirection = 'sendonly';\n\t\t\t\t\tif(transceiver.setDirection)\n\t\t\t\t\t\ttransceiver.setDirection(newDirection);\n\t\t\t\t\telse\n\t\t\t\t\t\ttransceiver.direction = newDirection;\n\t\t\t\t} else {\n\t\t\t\t\t// FIXME Add as a new track\n\t\t\t\t\tif(!config.myStream)\n\t\t\t\t\t\tconfig.myStream = new MediaStream();\n\t\t\t\t\tif(kind === 'audio' || (!track.simulcast && !track.svc)) {\n\t\t\t\t\t\tsender = config.pc.addTrack(nt, config.myStream);\n\t\t\t\t\t\ttransceiver = config.pc.getTransceivers()\n\t\t\t\t\t\t\t.find(t => (t.sender === sender));\n\t\t\t\t\t} else if(track.simulcast) {\n\t\t\t\t\t\tif(Janus.webRTCAdapter.browserDetails.browser !== 'firefox') {\n\t\t\t\t\t\t\t// Standard RID\n\t\t\t\t\t\t\tJanus.log('Enabling rid-based simulcasting:', nt);\n\t\t\t\t\t\t\tlet maxBitrates = getMaxBitrates(track.simulcastMaxBitrates);\n\t\t\t\t\t\t\ttransceiver = config.pc.addTransceiver(nt, {\n\t\t\t\t\t\t\t\tdirection: 'sendrecv',\n\t\t\t\t\t\t\t\tstreams: [config.myStream],\n\t\t\t\t\t\t\t\tsendEncodings: track.sendEncodings || [\n\t\t\t\t\t\t\t\t\t{ rid: 'h', active: true, maxBitrate: maxBitrates.high },\n\t\t\t\t\t\t\t\t\t{ rid: 'm', active: true, maxBitrate: maxBitrates.medium, scaleResolutionDownBy: 2 },\n\t\t\t\t\t\t\t\t\t{ rid: 'l', active: true, maxBitrate: maxBitrates.low, scaleResolutionDownBy: 4 }\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Firefox-based RID, based on https://gist.github.com/voluntas/088bc3cc62094730647b\n\t\t\t\t\t\t\tJanus.log('Enabling Simulcasting for Firefox (RID)');\n\t\t\t\t\t\t\ttransceiver = config.pc.addTransceiver(nt, {\n\t\t\t\t\t\t\t\tdirection: 'sendrecv',\n\t\t\t\t\t\t\t\tstreams: [config.myStream]\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tsender = transceiver ? transceiver.sender : null;\n\t\t\t\t\t\t\tif(sender) {\n\t\t\t\t\t\t\t\tlet parameters = sender.getParameters();\n\t\t\t\t\t\t\t\tif(!parameters)\n\t\t\t\t\t\t\t\t\tparameters = {};\n\t\t\t\t\t\t\t\tlet maxBitrates = getMaxBitrates(track.simulcastMaxBitrates);\n\t\t\t\t\t\t\t\tparameters.encodings = track.sendEncodings || [\n\t\t\t\t\t\t\t\t\t{ rid: 'h', active: true, maxBitrate: maxBitrates.high },\n\t\t\t\t\t\t\t\t\t{ rid: 'm', active: true, maxBitrate: maxBitrates.medium, scaleResolutionDownBy: 2 },\n\t\t\t\t\t\t\t\t\t{ rid: 'l', active: true, maxBitrate: maxBitrates.low, scaleResolutionDownBy: 4 }\n\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\tsender.setParameters(parameters);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tJanus.log('Enabling SVC (' + track.svc + '):', nt);\n\t\t\t\t\t\ttransceiver = config.pc.addTransceiver(nt, {\n\t\t\t\t\t\t\tdirection: 'sendrecv',\n\t\t\t\t\t\t\tstreams: [config.myStream],\n\t\t\t\t\t\t\tsendEncodings: [\n\t\t\t\t\t\t\t\t{ scalabilityMode: track.svc }\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif(!sender)\n\t\t\t\t\t\tsender = transceiver ? transceiver.sender : null;\n\t\t\t\t\t// Check if we need to override some settings\n\t\t\t\t\tif(track.codec) {\n\t\t\t\t\t\tif(Janus.webRTCAdapter.browserDetails.browser === 'firefox') {\n\t\t\t\t\t\t\tJanus.warn('setCodecPreferences not supported in Firefox, ignoring codec for track:', track);\n\t\t\t\t\t\t} else if(typeof track.codec !== 'string') {\n\t\t\t\t\t\t\tJanus.warn('Invalid codec value, ignoring for track:', track);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlet mimeType = kind + '/' + track.codec.toLowerCase();\n\t\t\t\t\t\t\tlet codecs = RTCRtpReceiver.getCapabilities(kind).codecs.filter(function(codec) {\n\t\t\t\t\t\t\t\treturn codec.mimeType.toLowerCase() === mimeType;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif(!codecs || codecs.length === 0) {\n\t\t\t\t\t\t\t\tJanus.warn('Codec not supported in this browser for this track, ignoring:', track);\n\t\t\t\t\t\t\t} else if(transceiver) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\ttransceiver.setCodecPreferences(codecs);\n\t\t\t\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\t\t\t\tJanus.warn('Failed enforcing codec for this ' + kind + ' track:', err);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(track.bitrate) {\n\t\t\t\t\t\t// Override maximum bitrate\n\t\t\t\t\t\tif(track.simulcast || track.svc) {\n\t\t\t\t\t\t\tJanus.warn('Ignoring bitrate for simulcast/SVC track, use sendEncodings for that');\n\t\t\t\t\t\t} else if(isNaN(track.bitrate) || track.bitrate < 0) {\n\t\t\t\t\t\t\tJanus.warn('Ignoring invalid bitrate for track:', track);\n\t\t\t\t\t\t} else if(sender) {\n\t\t\t\t\t\t\tlet params = sender.getParameters();\n\t\t\t\t\t\t\tif(!params || !params.encodings || params.encodings.length === 0) {\n\t\t\t\t\t\t\t\tJanus.warn('No encodings in the sender parameters, ignoring bitrate for track:', track);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tparams.encodings[0].maxBitrate = track.bitrate;\n\t\t\t\t\t\t\t\tawait sender.setParameters(params);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(kind === 'video' && track.framerate) {\n\t\t\t\t\t\t// Override maximum framerate\n\t\t\t\t\t\tif(track.simulcast || track.svc) {\n\t\t\t\t\t\t\tJanus.warn('Ignoring framerate for simulcast/SVC track, use sendEncodings for that');\n\t\t\t\t\t\t} else if(isNaN(track.framerate) || track.framerate < 0) {\n\t\t\t\t\t\t\tJanus.warn('Ignoring invalid framerate for track:', track);\n\t\t\t\t\t\t} else if(sender) {\n\t\t\t\t\t\t\tlet params = sender.getParameters();\n\t\t\t\t\t\t\tif(!params || !params.encodings || params.encodings.length === 0) {\n\t\t\t\t\t\t\t\tJanus.warn('No encodings in the sender parameters, ignoring framerate for track:', track);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tparams.encodings[0].maxFramerate = track.framerate;\n\t\t\t\t\t\t\t\tawait sender.setParameters(params);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Check if insertable streams are involved\n\t\t\t\t\tif(track.transforms) {\n\t\t\t\t\t\tif(sender && track.transforms.sender) {\n\t\t\t\t\t\t\t// There's a sender transform, set it on the transceiver sender\n\t\t\t\t\t\t\tlet senderStreams = null;\n\t\t\t\t\t\t\tif(RTCRtpSender.prototype.createEncodedStreams) {\n\t\t\t\t\t\t\t\tsenderStreams = sender.createEncodedStreams();\n\t\t\t\t\t\t\t} else if(RTCRtpSender.prototype.createAudioEncodedStreams || RTCRtpSender.prototype.createEncodedVideoStreams) {\n\t\t\t\t\t\t\t\tif(kind === 'audio') {\n\t\t\t\t\t\t\t\t\tsenderStreams = sender.createEncodedAudioStreams();\n\t\t\t\t\t\t\t\t} else if(kind === 'video') {\n\t\t\t\t\t\t\t\t\tsenderStreams = sender.createEncodedVideoStreams();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(senderStreams) {\n\t\t\t\t\t\t\t\tconsole.log('Insertable Streams sender transform:', senderStreams);\n\t\t\t\t\t\t\t\tif(senderStreams.readableStream && senderStreams.writableStream) {\n\t\t\t\t\t\t\t\t\tsenderStreams.readableStream\n\t\t\t\t\t\t\t\t\t\t.pipeThrough(track.transforms.sender)\n\t\t\t\t\t\t\t\t\t\t.pipeTo(senderStreams.writableStream);\n\t\t\t\t\t\t\t\t} else if(senderStreams.readable && senderStreams.writable) {\n\t\t\t\t\t\t\t\t\tsenderStreams.readable\n\t\t\t\t\t\t\t\t\t\t.pipeThrough(track.transforms.sender)\n\t\t\t\t\t\t\t\t\t\t.pipeTo(senderStreams.writable);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(transceiver && transceiver.receiver && track.transforms.receiver) {\n\t\t\t\t\t\t\t// There's a receiver transform, set it on the transceiver receiver\n\t\t\t\t\t\t\tlet receiverStreams = null;\n\t\t\t\t\t\t\tif(RTCRtpReceiver.prototype.createEncodedStreams) {\n\t\t\t\t\t\t\t\treceiverStreams = transceiver.receiver.createEncodedStreams();\n\t\t\t\t\t\t\t} else if(RTCRtpReceiver.prototype.createAudioEncodedStreams || RTCRtpReceiver.prototype.createEncodedVideoStreams) {\n\t\t\t\t\t\t\t\tif(kind === 'audio') {\n\t\t\t\t\t\t\t\t\treceiverStreams = transceiver.receiver.createEncodedAudioStreams();\n\t\t\t\t\t\t\t\t} else if(kind === 'video') {\n\t\t\t\t\t\t\t\t\treceiverStreams = transceiver.receiver.createEncodedVideoStreams();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(receiverStreams) {\n\t\t\t\t\t\t\t\tconsole.log('Insertable Streams receiver transform:', receiverStreams);\n\t\t\t\t\t\t\t\tif(receiverStreams.readableStream && receiverStreams.writableStream) {\n\t\t\t\t\t\t\t\t\treceiverStreams.readableStream\n\t\t\t\t\t\t\t\t\t\t.pipeThrough(track.transforms.receiver)\n\t\t\t\t\t\t\t\t\t\t.pipeTo(receiverStreams.writableStream);\n\t\t\t\t\t\t\t\t} else if(receiverStreams.readable && receiverStreams.writable) {\n\t\t\t\t\t\t\t\t\treceiverStreams.readable\n\t\t\t\t\t\t\t\t\t\t.pipeThrough(track.transforms.receiver)\n\t\t\t\t\t\t\t\t\t\t.pipeTo(receiverStreams.writable);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(nt && track.dontStop === true)\n\t\t\t\t\tnt.dontStop = true;\n\t\t\t} else if(track.recv && !transceiver) {\n\t\t\t\t// Maybe a new recvonly track\n\t\t\t\ttransceiver = config.pc.addTransceiver(kind);\n\t\t\t\tif(transceiver) {\n\t\t\t\t\t// Check if we need to override some settings\n\t\t\t\t\tif(track.codec) {\n\t\t\t\t\t\tif(Janus.webRTCAdapter.browserDetails.browser === 'firefox') {\n\t\t\t\t\t\t\tJanus.warn('setCodecPreferences not supported in Firefox, ignoring codec for track:', track);\n\t\t\t\t\t\t} else if(typeof track.codec !== 'string') {\n\t\t\t\t\t\t\tJanus.warn('Invalid codec value, ignoring for track:', track);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlet mimeType = kind + '/' + track.codec.toLowerCase();\n\t\t\t\t\t\t\tlet codecs = RTCRtpReceiver.getCapabilities(kind).codecs.filter(function(codec) {\n\t\t\t\t\t\t\t\treturn codec.mimeType.toLowerCase() === mimeType;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif(!codecs || codecs.length === 0) {\n\t\t\t\t\t\t\t\tJanus.warn('Codec not supported in this browser for this track, ignoring:', track);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\ttransceiver.setCodecPreferences(codecs);\n\t\t\t\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\t\t\t\tJanus.warn('Failed enforcing codec for this ' + kind + ' track:', err);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Check if insertable streams are involved\n\t\t\t\t\tif(transceiver.receiver && track.transforms && track.transforms.receiver) {\n\t\t\t\t\t\t// There's a receiver transform, set it on the transceiver receiver\n\t\t\t\t\t\tlet receiverStreams = null;\n\t\t\t\t\t\tif(RTCRtpReceiver.prototype.createEncodedStreams) {\n\t\t\t\t\t\t\treceiverStreams = transceiver.receiver.createEncodedStreams();\n\t\t\t\t\t\t} else if(RTCRtpReceiver.prototype.createAudioEncodedStreams || RTCRtpReceiver.prototype.createEncodedVideoStreams) {\n\t\t\t\t\t\t\tif(kind === 'audio') {\n\t\t\t\t\t\t\t\treceiverStreams = transceiver.receiver.createEncodedAudioStreams();\n\t\t\t\t\t\t\t} else if(kind === 'video') {\n\t\t\t\t\t\t\t\treceiverStreams = transceiver.receiver.createEncodedVideoStreams();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(receiverStreams) {\n\t\t\t\t\t\t\tconsole.log('Insertable Streams receiver transform:', receiverStreams);\n\t\t\t\t\t\t\tif(receiverStreams.readableStream && receiverStreams.writableStream) {\n\t\t\t\t\t\t\t\treceiverStreams.readableStream\n\t\t\t\t\t\t\t\t\t.pipeThrough(track.transforms.receiver)\n\t\t\t\t\t\t\t\t\t.pipeTo(receiverStreams.writableStream);\n\t\t\t\t\t\t\t} else if(receiverStreams.readable && receiverStreams.writable) {\n\t\t\t\t\t\t\t\treceiverStreams.readable\n\t\t\t\t\t\t\t\t\t.pipeThrough(track.transforms.receiver)\n\t\t\t\t\t\t\t\t\t.pipeTo(receiverStreams.writable);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Get rid of the old track\n\t\t\t// FIXME We should probably do this *before* capturing the new\n\t\t\t// track, since this prevents, for instance, just changing the\n\t\t\t// resolution of the same webcam we're capturing already (the\n\t\t\t// existing resolution would be returned, or an overconstrained\n\t\t\t// error). On the other end, closing the track before we capture\n\t\t\t// the new device means we'd end up with a period of time where\n\t\t\t// no video is sent (changing device takes some time), and\n\t\t\t// media would be stopped entirely in case capturing the new\n\t\t\t// device results in an error. To keep things simpler, we're\n\t\t\t// doing it after: we can make this configurable in the future.\n\t\t\tif(trackId && config.myStream) {\n\t\t\t\tlet rt = null;\n\t\t\t\tif(kind === 'audio' && config.myStream.getAudioTracks() && config.myStream.getAudioTracks().length) {\n\t\t\t\t\tfor(let t of config.myStream.getAudioTracks()) {\n\t\t\t\t\t\tif(t.id === trackId) {\n\t\t\t\t\t\t\trt = t;\n\t\t\t\t\t\t\tJanus.log('Removing audio track:', rt);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if(kind === 'video' && config.myStream.getVideoTracks() && config.myStream.getVideoTracks().length) {\n\t\t\t\t\tfor(let t of config.myStream.getVideoTracks()) {\n\t\t\t\t\t\tif(t.id === trackId) {\n\t\t\t\t\t\t\trt = t;\n\t\t\t\t\t\t\tJanus.log('Removing video track:', rt);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(rt) {\n\t\t\t\t\t// Remove the track and notify the application\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconfig.myStream.removeTrack(rt);\n\t\t\t\t\t\tpluginHandle.onlocaltrack(rt, false);\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\tJanus.error(\"Error calling onlocaltrack on removal for renegotiation\", e);\n\t\t\t\t\t}\n\t\t\t\t\t// Close the old track (unless we've been asked not to)\n\t\t\t\t\tif(rt.dontStop !== true) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\trt.stop();\n\t\t\t\t\t\t} catch(e) {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(nt) {\n\t\t\t\t// FIXME Add the new track locally\n\t\t\t\tconfig.myStream.addTrack(nt);\n\t\t\t\t// Notify the application about the new local track, if any\n\t\t\t\tnt.onended = function(ev) {\n\t\t\t\t\tJanus.log('Local track removed:', ev);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpluginHandle.onlocaltrack(ev.target, false);\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\tJanus.error(\"Error calling onlocaltrack following end\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tpluginHandle.onlocaltrack(nt, true);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tJanus.error(\"Error calling onlocaltrack for track add\", e);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Update the direction of the transceiver\n\t\t\tif(transceiver) {\n\t\t\t\tlet curdir = transceiver.direction, newdir = null;\n\t\t\t\tlet send = (nt && transceiver.sender.track),\n\t\t\t\t\trecv = (track.recv !== false && transceiver.receiver.track);\n\t\t\t\tif(send && recv)\n\t\t\t\t\tnewdir = 'sendrecv';\n\t\t\t\telse if(send && !recv)\n\t\t\t\t\tnewdir = 'sendonly';\n\t\t\t\telse if(!send && recv)\n\t\t\t\t\tnewdir = 'recvonly';\n\t\t\t\telse if(!send && !recv)\n\t\t\t\t\tnewdir = 'inactive';\n\t\t\t\tif(newdir && newdir !== curdir) {\n\t\t\t\t\tJanus.warn('Changing direction of transceiver to ' + newdir + ' (was ' + curdir + ')', track);\n\t\t\t\t\tif(transceiver.setDirection)\n\t\t\t\t\t\ttransceiver.setDirection(newdir);\n\t\t\t\t\telse\n\t\t\t\t\t\ttransceiver.direction = newdir;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(openedConsentDialog)\n\t\t\tpluginHandle.consentDialog(false);\n\t}\n\n\tfunction getLocalTracks(handleId) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn('Invalid handle');\n\t\t\treturn null;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.pc) {\n\t\t\tJanus.warn('Invalid PeerConnection');\n\t\t\treturn null;\n\t\t}\n\t\tlet tracks = [];\n\t\tlet transceivers = config.pc.getTransceivers();\n\t\tfor(let tr of transceivers) {\n\t\t\tlet track = null;\n\t\t\tif(tr.sender && tr.sender.track) {\n\t\t\t\ttrack = { mid: tr.mid };\n\t\t\t\ttrack.type = tr.sender.track.kind;\n\t\t\t\ttrack.id = tr.sender.track.id;\n\t\t\t\ttrack.label = tr.sender.track.label;\n\t\t\t}\n\t\t\tif(track)\n\t\t\t\ttracks.push(track);\n\t\t}\n\t\treturn tracks;\n\t}\n\n\tfunction getRemoteTracks(handleId) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn('Invalid handle');\n\t\t\treturn null;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.pc) {\n\t\t\tJanus.warn('Invalid PeerConnection');\n\t\t\treturn null;\n\t\t}\n\t\tlet tracks = [];\n\t\tlet transceivers = config.pc.getTransceivers();\n\t\tfor(let tr of transceivers) {\n\t\t\tlet track = null;\n\t\t\tif(tr.receiver && tr.receiver.track) {\n\t\t\t\ttrack = { mid: tr.mid };\n\t\t\t\ttrack.type = tr.receiver.track.kind;\n\t\t\t\ttrack.id = tr.receiver.track.id;\n\t\t\t\ttrack.label = tr.receiver.track.label;\n\t\t\t}\n\t\t\tif(track)\n\t\t\t\ttracks.push(track);\n\t\t}\n\t\treturn tracks;\n\t}\n\n\tfunction getVolume(handleId, mid, remote, result) {\n\t\tresult = (typeof result == \"function\") ? result : Janus.noop;\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\tresult(0);\n\t\t\treturn;\n\t\t}\n\t\tlet stream = remote ? \"remote\" : \"local\";\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.volume[stream])\n\t\t\tconfig.volume[stream] = { value: 0 };\n\t\t// Start getting the volume, if audioLevel in getStats is supported (apparently\n\t\t// they're only available in Chrome/Safari right now: https://webrtc-stats.callstats.io/)\n\t\tif(config.pc && config.pc.getStats && (Janus.webRTCAdapter.browserDetails.browser === \"chrome\" ||\n\t\t\t\tJanus.webRTCAdapter.browserDetails.browser === \"safari\")) {\n\t\t\t// Are we interested in a mid in particular?\n\t\t\tlet query = config.pc;\n\t\t\tif(mid) {\n\t\t\t\tlet transceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.mid === mid && t.receiver.track.kind === \"audio\"));\n\t\t\t\tif(!transceiver) {\n\t\t\t\t\tJanus.warn(\"No audio transceiver with mid \" + mid);\n\t\t\t\t\tresult(0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif(remote && !transceiver.receiver) {\n\t\t\t\t\tJanus.warn(\"Remote transceiver track unavailable\");\n\t\t\t\t\tresult(0);\n\t\t\t\t\treturn;\n\t\t\t\t} else if(!remote && !transceiver.sender) {\n\t\t\t\t\tJanus.warn(\"Local transceiver track unavailable\");\n\t\t\t\t\tresult(0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tquery = remote ? transceiver.receiver : transceiver.sender;\n\t\t\t}\n\t\t\tquery.getStats()\n\t\t\t\t.then(function(stats) {\n\t\t\t\t\tstats.forEach(function (res) {\n\t\t\t\t\t\tif(!res || res.kind !== \"audio\")\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tif((remote && !res.remoteSource) || (!remote && res.type !== \"media-source\"))\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tresult(res.audioLevel ? res.audioLevel : 0);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\treturn config.volume[stream].value;\n\t\t} else {\n\t\t\t// audioInputLevel and audioOutputLevel seem only available in Chrome? audioLevel\n\t\t\t// seems to be available on Chrome and Firefox, but they don't seem to work\n\t\t\tJanus.warn(\"Getting the \" + stream + \" volume unsupported by browser\");\n\t\t\tresult(0);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tfunction isMuted(handleId, mid, video) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\treturn true;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.pc) {\n\t\t\tJanus.warn(\"Invalid PeerConnection\");\n\t\t\treturn true;\n\t\t}\n\t\tif(!config.myStream) {\n\t\t\tJanus.warn(\"Invalid local MediaStream\");\n\t\t\treturn true;\n\t\t}\n\t\tif(video) {\n\t\t\t// Check video track\n\t\t\tif(!config.myStream.getVideoTracks() || config.myStream.getVideoTracks().length === 0) {\n\t\t\t\tJanus.warn(\"No video track\");\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(mid) {\n\t\t\t\tlet transceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.mid === mid && t.receiver.track.kind === \"video\"));\n\t\t\t\tif(!transceiver) {\n\t\t\t\t\tJanus.warn(\"No video transceiver with mid \" + mid);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif(!transceiver.sender || !transceiver.sender.track) {\n\t\t\t\t\tJanus.warn(\"No video sender with mid \" + mid);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn !transceiver.sender.track.enabled;\n\t\t\t} else {\n\t\t\t\treturn !config.myStream.getVideoTracks()[0].enabled;\n\t\t\t}\n\t\t} else {\n\t\t\t// Check audio track\n\t\t\tif(!config.myStream.getAudioTracks() || config.myStream.getAudioTracks().length === 0) {\n\t\t\t\tJanus.warn(\"No audio track\");\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif(mid) {\n\t\t\t\tlet transceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.mid === mid && t.receiver.track.kind === \"audio\"));\n\t\t\t\tif(!transceiver) {\n\t\t\t\t\tJanus.warn(\"No audio transceiver with mid \" + mid);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif(!transceiver.sender || !transceiver.sender.track) {\n\t\t\t\t\tJanus.warn(\"No audio sender with mid \" + mid);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn !transceiver.sender.track.enabled;\n\t\t\t} else {\n\t\t\t\treturn !config.myStream.getAudioTracks()[0].enabled;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction mute(handleId, mid, video, mute) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\treturn false;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.pc) {\n\t\t\tJanus.warn(\"Invalid PeerConnection\");\n\t\t\treturn false;\n\t\t}\n\t\tif(!config.myStream) {\n\t\t\tJanus.warn(\"Invalid local MediaStream\");\n\t\t\treturn false;\n\t\t}\n\t\tif(video) {\n\t\t\t// Mute/unmute video track\n\t\t\tif(!config.myStream.getVideoTracks() || config.myStream.getVideoTracks().length === 0) {\n\t\t\t\tJanus.warn(\"No video track\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(mid) {\n\t\t\t\tlet transceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.mid === mid && t.receiver.track.kind === \"video\"));\n\t\t\t\tif(!transceiver) {\n\t\t\t\t\tJanus.warn(\"No video transceiver with mid \" + mid);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif(!transceiver.sender || !transceiver.sender.track) {\n\t\t\t\t\tJanus.warn(\"No video sender with mid \" + mid);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\ttransceiver.sender.track.enabled = mute ? false : true;\n\t\t\t} else {\n\t\t\t\tfor(const videostream of config.myStream.getVideoTracks()) {\n\t\t\t\t\tvideostream.enabled = !mute\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Mute/unmute audio track\n\t\t\tif(!config.myStream.getAudioTracks() || config.myStream.getAudioTracks().length === 0) {\n\t\t\t\tJanus.warn(\"No audio track\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(mid) {\n\t\t\t\tlet transceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.mid === mid && t.receiver.track.kind === \"audio\"));\n\t\t\t\tif(!transceiver) {\n\t\t\t\t\tJanus.warn(\"No audio transceiver with mid \" + mid);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif(!transceiver.sender || !transceiver.sender.track) {\n\t\t\t\t\tJanus.warn(\"No audio sender with mid \" + mid);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\ttransceiver.sender.track.enabled = mute ? false : true;\n\t\t\t} else {\n\t\t\t\tfor(const audiostream of config.myStream.getAudioTracks()) {\n\t\t\t\t\taudiostream.enabled = !mute\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tfunction getBitrate(handleId, mid) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn(\"Invalid handle\");\n\t\t\treturn \"Invalid handle\";\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.pc)\n\t\t\treturn \"Invalid PeerConnection\";\n\t\t// Start getting the bitrate, if getStats is supported\n\t\tif(config.pc.getStats) {\n\t\t\tlet query = config.pc;\n\t\t\tlet target = mid ? mid : \"default\";\n\t\t\tif(mid) {\n\t\t\t\tlet transceiver = config.pc.getTransceivers()\n\t\t\t\t\t.find(t => (t.mid === mid && t.receiver.track.kind === \"video\"));\n\t\t\t\tif(!transceiver) {\n\t\t\t\t\tJanus.warn(\"No video transceiver with mid \" + mid);\n\t\t\t\t\treturn (\"No video transceiver with mid \" + mid);\n\t\t\t\t}\n\t\t\t\tif(!transceiver.receiver) {\n\t\t\t\t\tJanus.warn(\"No video receiver with mid \" + mid);\n\t\t\t\t\treturn (\"No video receiver with mid \" + mid);\n\t\t\t\t}\n\t\t\t\tquery = transceiver.receiver;\n\t\t\t}\n\t\t\tif(!config.bitrate[target]) {\n\t\t\t\tconfig.bitrate[target] = {\n\t\t\t\t\ttimer: null,\n\t\t\t\t\tbsnow: null,\n\t\t\t\t\tbsbefore: null,\n\t\t\t\t\ttsnow: null,\n\t\t\t\t\ttsbefore: null,\n\t\t\t\t\tvalue: \"0 kbits/sec\"\n\t\t\t\t};\n\t\t\t}\n\t\t\tif(!config.bitrate[target].timer) {\n\t\t\t\tJanus.log(\"Starting bitrate timer\" + (mid ? (\" for mid \" + mid) : \"\") + \" (via getStats)\");\n\t\t\t\tconfig.bitrate[target].timer = setInterval(function() {\n\t\t\t\t\tquery.getStats()\n\t\t\t\t\t\t.then(function(stats) {\n\t\t\t\t\t\t\tstats.forEach(function (res) {\n\t\t\t\t\t\t\t\tif(!res)\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\tlet inStats = false;\n\t\t\t\t\t\t\t\t// Check if these are statistics on incoming media\n\t\t\t\t\t\t\t\tif((res.mediaType === \"video\" || res.id.toLowerCase().indexOf(\"video\") > -1) &&\n\t\t\t\t\t\t\t\t\t\tres.type === \"inbound-rtp\" && res.id.indexOf(\"rtcp\") < 0) {\n\t\t\t\t\t\t\t\t\t// New stats\n\t\t\t\t\t\t\t\t\tinStats = true;\n\t\t\t\t\t\t\t\t} else if(res.type == 'ssrc' && res.bytesReceived &&\n\t\t\t\t\t\t\t\t\t\t(res.googCodecName === \"VP8\" || res.googCodecName === \"\")) {\n\t\t\t\t\t\t\t\t\t// Older Chromer versions\n\t\t\t\t\t\t\t\t\tinStats = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Parse stats now\n\t\t\t\t\t\t\t\tif(inStats) {\n\t\t\t\t\t\t\t\t\tconfig.bitrate[target].bsnow = res.bytesReceived;\n\t\t\t\t\t\t\t\t\tconfig.bitrate[target].tsnow = res.timestamp;\n\t\t\t\t\t\t\t\t\tif(config.bitrate[target].bsbefore === null || config.bitrate[target].tsbefore === null) {\n\t\t\t\t\t\t\t\t\t\t// Skip this round\n\t\t\t\t\t\t\t\t\t\tconfig.bitrate[target].bsbefore = config.bitrate[target].bsnow;\n\t\t\t\t\t\t\t\t\t\tconfig.bitrate[target].tsbefore = config.bitrate[target].tsnow;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t// Calculate bitrate\n\t\t\t\t\t\t\t\t\t\tlet timePassed = config.bitrate[target].tsnow - config.bitrate[target].tsbefore;\n\t\t\t\t\t\t\t\t\t\tif(Janus.webRTCAdapter.browserDetails.browser === \"safari\")\n\t\t\t\t\t\t\t\t\t\t\ttimePassed = timePassed/1000;\t// Apparently the timestamp is in microseconds, in Safari\n\t\t\t\t\t\t\t\t\t\tlet bitRate = Math.round((config.bitrate[target].bsnow - config.bitrate[target].bsbefore) * 8 / timePassed);\n\t\t\t\t\t\t\t\t\t\tif(Janus.webRTCAdapter.browserDetails.browser === \"safari\")\n\t\t\t\t\t\t\t\t\t\t\tbitRate = parseInt(bitRate/1000);\n\t\t\t\t\t\t\t\t\t\tconfig.bitrate[target].value = bitRate + ' kbits/sec';\n\t\t\t\t\t\t\t\t\t\t//~ Janus.log(\"Estimated bitrate is \" + config.bitrate.value);\n\t\t\t\t\t\t\t\t\t\tconfig.bitrate[target].bsbefore = config.bitrate[target].bsnow;\n\t\t\t\t\t\t\t\t\t\tconfig.bitrate[target].tsbefore = config.bitrate[target].tsnow;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t}, 1000);\n\t\t\t\treturn \"0 kbits/sec\";\t// We don't have a bitrate value yet\n\t\t\t}\n\t\t\treturn config.bitrate[target].value;\n\t\t} else {\n\t\t\tJanus.warn(\"Getting the video bitrate unsupported by browser\");\n\t\t\treturn \"Feature unsupported by browser\";\n\t\t}\n\t}\n\n\tfunction setBitrate(handleId, mid, bitrate) {\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle || !pluginHandle.webrtcStuff) {\n\t\t\tJanus.warn('Invalid handle');\n\t\t\treturn;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(!config.pc) {\n\t\t\tJanus.warn('Invalid PeerConnection');\n\t\t\treturn;\n\t\t}\n\t\tlet transceiver = config.pc.getTransceivers().find(t => (t.mid === mid));\n\t\tif(!transceiver) {\n\t\t\tJanus.warn('No transceiver with mid', mid);\n\t\t\treturn;\n\t\t}\n\t\tif(!transceiver.sender) {\n\t\t\tJanus.warn('No sender for transceiver with mid', mid);\n\t\t\treturn;\n\t\t}\n\t\tlet params = transceiver.sender.getParameters();\n\t\tif(!params || !params.encodings || params.encodings.length === 0) {\n\t\t\tJanus.warn('No parameters encodings');\n\t\t} else if(params.encodings.length > 1) {\n\t\t\tJanus.warn('Ignoring bitrate for simulcast track, use sendEncodings for that');\n\t\t} else if(isNaN(bitrate) || bitrate < 0) {\n\t\t\tJanus.warn('Invalid bitrate (must be a positive integer)');\n\t\t} else {\n\t\t\tparams.encodings[0].maxBitrate = bitrate;\n\t\t\ttransceiver.sender.setParameters(params);\n\t\t}\n\t}\n\n\tfunction webrtcError(error) {\n\t\tJanus.error(\"WebRTC error:\", error);\n\t}\n\n\tfunction cleanupWebrtc(handleId, hangupRequest) {\n\t\tJanus.log(\"Cleaning WebRTC stuff\");\n\t\tlet pluginHandle = pluginHandles[handleId];\n\t\tif(!pluginHandle) {\n\t\t\t// Nothing to clean\n\t\t\treturn;\n\t\t}\n\t\tlet config = pluginHandle.webrtcStuff;\n\t\tif(config) {\n\t\t\tif(hangupRequest === true) {\n\t\t\t\t// Send a hangup request (we don't really care about the response)\n\t\t\t\tlet request = { \"janus\": \"hangup\", \"transaction\": Janus.randomString(12) };\n\t\t\t\tif(pluginHandle.token)\n\t\t\t\t\trequest[\"token\"] = pluginHandle.token;\n\t\t\t\tif(apisecret)\n\t\t\t\t\trequest[\"apisecret\"] = apisecret;\n\t\t\t\tJanus.debug(\"Sending hangup request (handle=\" + handleId + \"):\");\n\t\t\t\tJanus.debug(request);\n\t\t\t\tif(websockets) {\n\t\t\t\t\trequest[\"session_id\"] = sessionId;\n\t\t\t\t\trequest[\"handle_id\"] = handleId;\n\t\t\t\t\tws.send(JSON.stringify(request));\n\t\t\t\t} else {\n\t\t\t\t\tJanus.httpAPICall(server + \"/\" + sessionId + \"/\" + handleId, {\n\t\t\t\t\t\tverb: 'POST',\n\t\t\t\t\t\twithCredentials: withCredentials,\n\t\t\t\t\t\tbody: request\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Cleanup stack\n\t\t\tif(config.volume) {\n\t\t\t\tif(config.volume[\"local\"] && config.volume[\"local\"].timer)\n\t\t\t\t\tclearInterval(config.volume[\"local\"].timer);\n\t\t\t\tif(config.volume[\"remote\"] && config.volume[\"remote\"].timer)\n\t\t\t\t\tclearInterval(config.volume[\"remote\"].timer);\n\t\t\t}\n\t\t\tfor(let i in config.bitrate) {\n\t\t\t\tif(config.bitrate[i].timer)\n\t\t\t\t\tclearInterval(config.bitrate[i].timer);\n\t\t\t}\n\t\t\tconfig.bitrate = {};\n\t\t\tif(!config.streamExternal && config.myStream) {\n\t\t\t\tJanus.log(\"Stopping local stream tracks\");\n\t\t\t\tJanus.stopAllTracks(config.myStream);\n\t\t\t}\n\t\t\tconfig.streamExternal = false;\n\t\t\tconfig.myStream = null;\n\t\t\t// Close PeerConnection\n\t\t\ttry {\n\t\t\t\tconfig.pc.close();\n\t\t\t} catch(e) {\n\t\t\t\t// Do nothing\n\t\t\t}\n\t\t\tconfig.pc = null;\n\t\t\tconfig.candidates = null;\n\t\t\tconfig.mySdp = null;\n\t\t\tconfig.remoteSdp = null;\n\t\t\tconfig.iceDone = false;\n\t\t\tconfig.dataChannel = {};\n\t\t\tconfig.dtmfSender = null;\n\t\t\tconfig.insertableStreams = false;\n\t\t}\n\t\tpluginHandle.oncleanup();\n\t}\n\n\tfunction isTrickleEnabled(trickle) {\n\t\tJanus.debug(\"isTrickleEnabled:\", trickle);\n\t\treturn (trickle === false) ? false : true;\n\t}\n}\n"
  },
  {
    "path": "wolf_demo/wasm/www/janus_env.js",
    "content": "// We use this shared JavaScript file as a simple way to have all demos\n// refer to the same settings, e.g., in terms of which server to connect\n// to or which STUN/TURN servers to use. This is helpful any time Janus\n// and its demos need to be deployed in a different environment, and\n// so all demos can be installed as are, by just updating the settings.js\n// file accordingly to account for the custom changes.\n//\n// We make use of this 'server' variable to provide the address of the\n// Janus API backend. By default, in this example we assume that Janus is\n// co-located with the web server hosting the HTML pages but listening\n// on a different port (8088, the default for HTTP in Janus), which is\n// why we make use of the 'window.location.hostname' base address. Since\n// Janus can also do HTTPS, and considering we don't really want to make\n// use of HTTP for Janus if your demos are served on HTTPS, we also rely\n// on the 'window.location.protocol' prefix to build the variable, in\n// particular to also change the port used to contact Janus (8088 for\n// HTTP and 8089 for HTTPS, if enabled).\n// In case you place Janus behind an Apache frontend (as we did on the\n// online demos at http://janus.conf.meetecho.com) you can just use a\n// relative path for the variable, e.g.:\n//\n// \t\tvar server = \"/janus\";\n//\n// which will take care of this on its own.\n//\n// If you want to use the WebSockets frontend to Janus, instead (which\n// is what we recommend, since they're more efficient than the long polling\n// we do with HTTP), you'll have to pass a different kind of address, e.g.:\n//\n// \t\tvar server = \"ws://\" + window.location.hostname + \":8188\";\n//\n// Of course this assumes that support for WebSockets has been built in\n// when compiling the server. Notice that the \"ws://\" prefix assumes\n// plain HTTP usage, so \"wss://\" should be used instead when using\n// WebSockets on HTTPS.//\n//\n// If you have multiple options available, and want to let the library\n// autodetect the best way to contact your server (or pool of servers),\n// you can also pass an array of servers, e.g., to provide alternative\n// means of access (e.g., try WebSockets first and, if that fails, fall\n// back to plain HTTP) or just have failover servers:\n//\n//\t\tvar server = [\n//\t\t\t\"ws://\" + window.location.hostname + \":8188\",\n//\t\t\t\"/janus\"\n//\t\t];\n//\n// This will tell the library to try connecting to each of the servers\n// in the presented order. The first working server will be used for\n// the whole session.\n//\nvar server = null;\nif (window.location.protocol === 'http:')\n  server = \"http://\" + window.location.hostname + \":8088/janus\";\nelse\n  server = \"https://\" + window.location.hostname + \":8089/janus\";\n\n// When creating a Janus object, we can also specify which STUN/TURN\n// servers we'd like to use to gather additional candidates. This is\n// done by passing an \"iceServers\" property when creating the Janus\n// object, meaning that the same set of servers will be used for all\n// PeerConnections that will be initialized within the context of the\n// new Janus session. When no iceServers object is provided, the janus.js\n// library automatically uses the free Google STUN servers, which means\n// it's equivalent to setting:\n//\n//\t\tvar iceServers = [{urls: \"stun:stun.l.google.com:19302\"}];\n//\n// Here are some examples of how an iceServers field may look like to\n// support TURN instead. Notice that, when a TURN server is configured,\n// there's no need to set a STUN one as well, since the TURN server will\n// be automatically contacted as a STUN server too, meaning it will be\n// used to gather both server reflexive and relay candidates.\n//\n//\t\tvar iceServers = [{urls: \"turn:yourturnserver.com:3478\",\n// username: \"janususer\", credential: \"januspwd\"}] \t\tvar iceServers:\n//[{urls: \"turn:yourturnserver.com:443?transport=tcp\", username: \"janususer\",\n// credential: \"januspwd\"}] \t\tvar iceServers: [{urls:\n//\"turns:yourturnserver.com:443?transport=tcp\", username: \"janususer\",\n// credential: \"januspwd\"}]\n//\n// By default we leave the iceServers variable empty, which again means\n// janus.js will fallback to the Google STUN server by default:\n//\nvar ice_servers = null;\n\n// var janus = null;\n// var screentest = null;\n\n// var username = null;\n// var id = null;\n\n// var capture = null;\n// var role = null;\n// var room = null;\n// var source = null;\n\n// var spinner = null;\n"
  },
  {
    "path": "wolf_demo/wasm/www/wolf.js",
    "content": "\n\n// The Module object: Our interface to the outside world. We import\n// and export values on it. There are various ways Module can be used:\n// 1. Not defined. We create it here\n// 2. A function parameter, function(Module) { ..generated code.. }\n// 3. pre-run appended it, var Module = {}; ..generated code..\n// 4. External script tag defines var Module.\n// We need to check if Module already exists (e.g. case 3 above).\n// Substitution will be replaced with actual code on later stage of the build,\n// this way Closure Compiler will not mangle it (e.g. case 4. above).\n// Note that if you want to run closure, and also to use Module\n// after the generated code, you will need to define   var Module = {};\n// before the code. Then that object will be used in the code, and you\n// can continue to use Module afterwards as well.\nvar Module = typeof Module != 'undefined' ? Module : {};\n\n// See https://caniuse.com/mdn-javascript_builtins_object_assign\n\n// See https://caniuse.com/mdn-javascript_builtins_bigint64array\n\n// --pre-jses are emitted after the Module integration code, so that they can\n// refer to Module (if they choose; they can also define Module)\n// {{PRE_JSES}}\n\n// Sometimes an existing Module object exists with properties\n// meant to overwrite the default module functionality. Here\n// we collect those properties and reapply _after_ we configure\n// the current environment's defaults to avoid having to be so\n// defensive during initialization.\nvar moduleOverrides = Object.assign({}, Module);\n\nvar arguments_ = [];\nvar thisProgram = './this.program';\nvar quit_ = (status, toThrow) => {\n  throw toThrow;\n};\n\n// Determine the runtime environment we are in. You can customize this by\n// setting the ENVIRONMENT setting at compile time (see settings.js).\n\n// Attempt to auto-detect the environment\nvar ENVIRONMENT_IS_WEB = typeof window == 'object';\nvar ENVIRONMENT_IS_WORKER = typeof importScripts == 'function';\n// N.b. Electron.js environment is simultaneously a NODE-environment, but\n// also a web environment.\nvar ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string';\nvar ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;\n\nif (Module['ENVIRONMENT']) {\n  throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)');\n}\n\n// `/` should be present at the end if `scriptDirectory` is not empty\nvar scriptDirectory = '';\nfunction locateFile(path) {\n  if (Module['locateFile']) {\n    return Module['locateFile'](path, scriptDirectory);\n  }\n  return scriptDirectory + path;\n}\n\n// Hooks that are implemented differently in different runtime environments.\nvar read_,\n    readAsync,\n    readBinary,\n    setWindowTitle;\n\n// Normally we don't log exceptions but instead let them bubble out the top\n// level where the embedding environment (e.g. the browser) can handle\n// them.\n// However under v8 and node we sometimes exit the process direcly in which case\n// its up to use us to log the exception before exiting.\n// If we fix https://github.com/emscripten-core/emscripten/issues/15080\n// this may no longer be needed under node.\nfunction logExceptionOnExit(e) {\n  if (e instanceof ExitStatus) return;\n  let toLog = e;\n  if (e && typeof e == 'object' && e.stack) {\n    toLog = [e, e.stack];\n  }\n  err('exiting due to exception: ' + toLog);\n}\n\nif (ENVIRONMENT_IS_NODE) {\n  if (typeof process == 'undefined' || !process.release || process.release.name !== 'node') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');\n  // `require()` is no-op in an ESM module, use `createRequire()` to construct\n  // the require()` function.  This is only necessary for multi-environment\n  // builds, `-sENVIRONMENT=node` emits a static import declaration instead.\n  // TODO: Swap all `require()`'s with `import()`'s?\n  // These modules will usually be used on Node.js. Load them eagerly to avoid\n  // the complexity of lazy-loading.\n  var fs = require('fs');\n  var nodePath = require('path');\n\n  if (ENVIRONMENT_IS_WORKER) {\n    scriptDirectory = nodePath.dirname(scriptDirectory) + '/';\n  } else {\n    scriptDirectory = __dirname + '/';\n  }\n\n// include: node_shell_read.js\n\n\nread_ = (filename, binary) => {\n  // We need to re-wrap `file://` strings to URLs. Normalizing isn't\n  // necessary in that case, the path should already be absolute.\n  filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);\n  return fs.readFileSync(filename, binary ? undefined : 'utf8');\n};\n\nreadBinary = (filename) => {\n  var ret = read_(filename, true);\n  if (!ret.buffer) {\n    ret = new Uint8Array(ret);\n  }\n  assert(ret.buffer);\n  return ret;\n};\n\nreadAsync = (filename, onload, onerror) => {\n  // See the comment in the `read_` function.\n  filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);\n  fs.readFile(filename, function(err, data) {\n    if (err) onerror(err);\n    else onload(data.buffer);\n  });\n};\n\n// end include: node_shell_read.js\n  if (process['argv'].length > 1) {\n    thisProgram = process['argv'][1].replace(/\\\\/g, '/');\n  }\n\n  arguments_ = process['argv'].slice(2);\n\n  if (typeof module != 'undefined') {\n    module['exports'] = Module;\n  }\n\n  process['on']('uncaughtException', function(ex) {\n    // suppress ExitStatus exceptions from showing an error\n    if (!(ex instanceof ExitStatus)) {\n      throw ex;\n    }\n  });\n\n  // Without this older versions of node (< v15) will log unhandled rejections\n  // but return 0, which is not normally the desired behaviour.  This is\n  // not be needed with node v15 and about because it is now the default\n  // behaviour:\n  // See https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode\n  process['on']('unhandledRejection', function(reason) { throw reason; });\n\n  quit_ = (status, toThrow) => {\n    if (keepRuntimeAlive()) {\n      process['exitCode'] = status;\n      throw toThrow;\n    }\n    logExceptionOnExit(toThrow);\n    process['exit'](status);\n  };\n\n  Module['inspect'] = function () { return '[Emscripten Module object]'; };\n\n} else\nif (ENVIRONMENT_IS_SHELL) {\n\n  if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');\n\n  if (typeof read != 'undefined') {\n    read_ = function shell_read(f) {\n      return read(f);\n    };\n  }\n\n  readBinary = function readBinary(f) {\n    let data;\n    if (typeof readbuffer == 'function') {\n      return new Uint8Array(readbuffer(f));\n    }\n    data = read(f, 'binary');\n    assert(typeof data == 'object');\n    return data;\n  };\n\n  readAsync = function readAsync(f, onload, onerror) {\n    setTimeout(() => onload(readBinary(f)), 0);\n  };\n\n  if (typeof scriptArgs != 'undefined') {\n    arguments_ = scriptArgs;\n  } else if (typeof arguments != 'undefined') {\n    arguments_ = arguments;\n  }\n\n  if (typeof quit == 'function') {\n    quit_ = (status, toThrow) => {\n      logExceptionOnExit(toThrow);\n      quit(status);\n    };\n  }\n\n  if (typeof print != 'undefined') {\n    // Prefer to use print/printErr where they exist, as they usually work better.\n    if (typeof console == 'undefined') console = /** @type{!Console} */({});\n    console.log = /** @type{!function(this:Console, ...*): undefined} */ (print);\n    console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr != 'undefined' ? printErr : print);\n  }\n\n} else\n\n// Note that this includes Node.js workers when relevant (pthreads is enabled).\n// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and\n// ENVIRONMENT_IS_NODE.\nif (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {\n  if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled\n    scriptDirectory = self.location.href;\n  } else if (typeof document != 'undefined' && document.currentScript) { // web\n    scriptDirectory = document.currentScript.src;\n  }\n  // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them.\n  // otherwise, slice off the final part of the url to find the script directory.\n  // if scriptDirectory does not contain a slash, lastIndexOf will return -1,\n  // and scriptDirectory will correctly be replaced with an empty string.\n  // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #),\n  // they are removed because they could contain a slash.\n  if (scriptDirectory.indexOf('blob:') !== 0) {\n    scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, \"\").lastIndexOf('/')+1);\n  } else {\n    scriptDirectory = '';\n  }\n\n  if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');\n\n  // Differentiate the Web Worker from the Node Worker case, as reading must\n  // be done differently.\n  {\n// include: web_or_worker_shell_read.js\n\n\n  read_ = (url) => {\n      var xhr = new XMLHttpRequest();\n      xhr.open('GET', url, false);\n      xhr.send(null);\n      return xhr.responseText;\n  }\n\n  if (ENVIRONMENT_IS_WORKER) {\n    readBinary = (url) => {\n        var xhr = new XMLHttpRequest();\n        xhr.open('GET', url, false);\n        xhr.responseType = 'arraybuffer';\n        xhr.send(null);\n        return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response));\n    };\n  }\n\n  readAsync = (url, onload, onerror) => {\n    var xhr = new XMLHttpRequest();\n    xhr.open('GET', url, true);\n    xhr.responseType = 'arraybuffer';\n    xhr.onload = () => {\n      if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0\n        onload(xhr.response);\n        return;\n      }\n      onerror();\n    };\n    xhr.onerror = onerror;\n    xhr.send(null);\n  }\n\n// end include: web_or_worker_shell_read.js\n  }\n\n  setWindowTitle = (title) => document.title = title;\n} else\n{\n  throw new Error('environment detection error');\n}\n\nvar out = Module['print'] || console.log.bind(console);\nvar err = Module['printErr'] || console.warn.bind(console);\n\n// Merge back in the overrides\nObject.assign(Module, moduleOverrides);\n// Free the object hierarchy contained in the overrides, this lets the GC\n// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.\nmoduleOverrides = null;\ncheckIncomingModuleAPI();\n\n// Emit code to handle expected values on the Module object. This applies Module.x\n// to the proper local x. This has two benefits: first, we only emit it if it is\n// expected to arrive, and second, by using a local everywhere else that can be\n// minified.\n\nif (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_');\n\nif (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram');\n\nif (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_');\n\n// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message\n// Assertions on removed incoming Module JS APIs.\nassert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead');\nassert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead');\nassert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead');\nassert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead');\nassert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)');\nassert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)');\nassert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');\nassert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)');\nassert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');\nlegacyModuleProp('read', 'read_');\nlegacyModuleProp('readAsync', 'readAsync');\nlegacyModuleProp('readBinary', 'readBinary');\nlegacyModuleProp('setWindowTitle', 'setWindowTitle');\nvar IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js';\nvar PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js';\nvar WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js';\nvar NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js';\n\nassert(!ENVIRONMENT_IS_SHELL, \"shell environment detected but not enabled at build time.  Add 'shell' to `-sENVIRONMENT` to enable.\");\n\n// include: support.js\n\n\nvar STACK_ALIGN = 16;\nvar POINTER_SIZE = 4;\n\nfunction getNativeTypeSize(type) {\n  switch (type) {\n    case 'i1': case 'i8': case 'u8': return 1;\n    case 'i16': case 'u16': return 2;\n    case 'i32': case 'u32': return 4;\n    case 'i64': case 'u64': return 8;\n    case 'float': return 4;\n    case 'double': return 8;\n    default: {\n      if (type[type.length - 1] === '*') {\n        return POINTER_SIZE;\n      }\n      if (type[0] === 'i') {\n        const bits = Number(type.substr(1));\n        assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type);\n        return bits / 8;\n      }\n      return 0;\n    }\n  }\n}\n\n// include: runtime_debug.js\n\n\nfunction legacyModuleProp(prop, newName) {\n  if (!Object.getOwnPropertyDescriptor(Module, prop)) {\n    Object.defineProperty(Module, prop, {\n      configurable: true,\n      get: function() {\n        abort('Module.' + prop + ' has been replaced with plain ' + newName + ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)');\n      }\n    });\n  }\n}\n\nfunction ignoredModuleProp(prop) {\n  if (Object.getOwnPropertyDescriptor(Module, prop)) {\n    abort('`Module.' + prop + '` was supplied but `' + prop + '` not included in INCOMING_MODULE_JS_API');\n  }\n}\n\n// forcing the filesystem exports a few things by default\nfunction isExportedByForceFilesystem(name) {\n  return name === 'FS_createPath' ||\n         name === 'FS_createDataFile' ||\n         name === 'FS_createPreloadedFile' ||\n         name === 'FS_unlink' ||\n         name === 'addRunDependency' ||\n         // The old FS has some functionality that WasmFS lacks.\n         name === 'FS_createLazyFile' ||\n         name === 'FS_createDevice' ||\n         name === 'removeRunDependency';\n}\n\nfunction missingGlobal(sym, msg) {\n  Object.defineProperty(globalThis, sym, {\n    configurable: true,\n    get: function() {\n      warnOnce('`' + sym + '` is not longer defined by emscripten. ' + msg);\n      return undefined;\n    }\n  });\n}\n\nmissingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer');\n\nfunction missingLibrarySymbol(sym) {\n  if (typeof globalThis !== 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) {\n    Object.defineProperty(globalThis, sym, {\n      configurable: true,\n      get: function() {\n        // Can't `abort()` here because it would break code that does runtime\n        // checks.  e.g. `if (typeof SDL === 'undefined')`.\n        var msg = '`' + sym + '` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line';\n        // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in\n        // library.js, which means $name for a JS name with no prefix, or name\n        // for a JS name like _name.\n        var librarySymbol = sym;\n        if (!librarySymbol.startsWith('_')) {\n          librarySymbol = '$' + sym;\n        }\n        msg += \" (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=\" + librarySymbol + \")\";\n        if (isExportedByForceFilesystem(sym)) {\n          msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';\n        }\n        warnOnce(msg);\n        return undefined;\n      }\n    });\n  }\n}\n\nfunction unexportedRuntimeSymbol(sym) {\n  if (!Object.getOwnPropertyDescriptor(Module, sym)) {\n    Object.defineProperty(Module, sym, {\n      configurable: true,\n      get: function() {\n        var msg = \"'\" + sym + \"' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)\";\n        if (isExportedByForceFilesystem(sym)) {\n          msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';\n        }\n        abort(msg);\n      }\n    });\n  }\n}\n\n// end include: runtime_debug.js\n// end include: support.js\n\n\n\n// === Preamble library stuff ===\n\n// Documentation for the public APIs defined in this file must be updated in:\n//    site/source/docs/api_reference/preamble.js.rst\n// A prebuilt local version of the documentation is available at:\n//    site/build/text/docs/api_reference/preamble.js.txt\n// You can also build docs locally as HTML or other formats in site/\n// An online HTML version (which may be of a different version of Emscripten)\n//    is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html\n\nvar wasmBinary;\nif (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary');\nvar noExitRuntime = Module['noExitRuntime'] || true;legacyModuleProp('noExitRuntime', 'noExitRuntime');\n\nif (typeof WebAssembly != 'object') {\n  abort('no native wasm support detected');\n}\n\n// Wasm globals\n\nvar wasmMemory;\n\n//========================================\n// Runtime essentials\n//========================================\n\n// whether we are quitting the application. no code should run after this.\n// set in exit() and abort()\nvar ABORT = false;\n\n// set by exit() and abort().  Passed to 'onExit' handler.\n// NOTE: This is also used as the process return code code in shell environments\n// but only when noExitRuntime is false.\nvar EXITSTATUS;\n\n/** @type {function(*, string=)} */\nfunction assert(condition, text) {\n  if (!condition) {\n    abort('Assertion failed' + (text ? ': ' + text : ''));\n  }\n}\n\n// We used to include malloc/free by default in the past. Show a helpful error in\n// builds with assertions.\n\n// include: runtime_strings.js\n\n\n// runtime_strings.js: String related runtime functions that are part of both\n// MINIMAL_RUNTIME and regular runtime.\n\nvar UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined;\n\n/**\n * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given\n * array that contains uint8 values, returns a copy of that string as a\n * Javascript String object.\n * heapOrArray is either a regular array, or a JavaScript typed array view.\n * @param {number} idx\n * @param {number=} maxBytesToRead\n * @return {string}\n */\nfunction UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {\n  var endIdx = idx + maxBytesToRead;\n  var endPtr = idx;\n  // TextDecoder needs to know the byte length in advance, it doesn't stop on\n  // null terminator by itself.  Also, use the length info to avoid running tiny\n  // strings through TextDecoder, since .subarray() allocates garbage.\n  // (As a tiny code save trick, compare endPtr against endIdx using a negation,\n  // so that undefined means Infinity)\n  while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;\n\n  if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {\n    return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));\n  }\n  var str = '';\n  // If building with TextDecoder, we have already computed the string length\n  // above, so test loop end condition against that\n  while (idx < endPtr) {\n    // For UTF8 byte structure, see:\n    // http://en.wikipedia.org/wiki/UTF-8#Description\n    // https://www.ietf.org/rfc/rfc2279.txt\n    // https://tools.ietf.org/html/rfc3629\n    var u0 = heapOrArray[idx++];\n    if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }\n    var u1 = heapOrArray[idx++] & 63;\n    if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }\n    var u2 = heapOrArray[idx++] & 63;\n    if ((u0 & 0xF0) == 0xE0) {\n      u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;\n    } else {\n      if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');\n      u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);\n    }\n\n    if (u0 < 0x10000) {\n      str += String.fromCharCode(u0);\n    } else {\n      var ch = u0 - 0x10000;\n      str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));\n    }\n  }\n  return str;\n}\n\n/**\n * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the\n * emscripten HEAP, returns a copy of that string as a Javascript String object.\n *\n * @param {number} ptr\n * @param {number=} maxBytesToRead - An optional length that specifies the\n *   maximum number of bytes to read. You can omit this parameter to scan the\n *   string until the first \\0 byte. If maxBytesToRead is passed, and the string\n *   at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the\n *   string will cut short at that byte index (i.e. maxBytesToRead will not\n *   produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing\n *   frequent uses of UTF8ToString() with and without maxBytesToRead may throw\n *   JS JIT optimizations off, so it is worth to consider consistently using one\n * @return {string}\n */\nfunction UTF8ToString(ptr, maxBytesToRead) {\n  return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';\n}\n\n/**\n * Copies the given Javascript String object 'str' to the given byte array at\n * address 'outIdx', encoded in UTF8 form and null-terminated. The copy will\n * require at most str.length*4+1 bytes of space in the HEAP.  Use the function\n * lengthBytesUTF8 to compute the exact number of bytes (excluding null\n * terminator) that this function will write.\n *\n * @param {string} str - The Javascript string to copy.\n * @param {ArrayBufferView|Array<number>} heap - The array to copy to. Each\n *                                               index in this array is assumed\n *                                               to be one 8-byte element.\n * @param {number} outIdx - The starting offset in the array to begin the copying.\n * @param {number} maxBytesToWrite - The maximum number of bytes this function\n *                                   can write to the array.  This count should\n *                                   include the null terminator, i.e. if\n *                                   maxBytesToWrite=1, only the null terminator\n *                                   will be written and nothing else.\n *                                   maxBytesToWrite=0 does not write any bytes\n *                                   to the output, not even the null\n *                                   terminator.\n * @return {number} The number of bytes written, EXCLUDING the null terminator.\n */\nfunction stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {\n  // Parameter maxBytesToWrite is not optional. Negative values, 0, null,\n  // undefined and false each don't write out any bytes.\n  if (!(maxBytesToWrite > 0))\n    return 0;\n\n  var startIdx = outIdx;\n  var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.\n  for (var i = 0; i < str.length; ++i) {\n    // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code\n    // unit, not a Unicode code point of the character! So decode\n    // UTF16->UTF32->UTF8.\n    // See http://unicode.org/faq/utf_bom.html#utf16-3\n    // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description\n    // and https://www.ietf.org/rfc/rfc2279.txt\n    // and https://tools.ietf.org/html/rfc3629\n    var u = str.charCodeAt(i); // possibly a lead surrogate\n    if (u >= 0xD800 && u <= 0xDFFF) {\n      var u1 = str.charCodeAt(++i);\n      u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);\n    }\n    if (u <= 0x7F) {\n      if (outIdx >= endIdx) break;\n      heap[outIdx++] = u;\n    } else if (u <= 0x7FF) {\n      if (outIdx + 1 >= endIdx) break;\n      heap[outIdx++] = 0xC0 | (u >> 6);\n      heap[outIdx++] = 0x80 | (u & 63);\n    } else if (u <= 0xFFFF) {\n      if (outIdx + 2 >= endIdx) break;\n      heap[outIdx++] = 0xE0 | (u >> 12);\n      heap[outIdx++] = 0x80 | ((u >> 6) & 63);\n      heap[outIdx++] = 0x80 | (u & 63);\n    } else {\n      if (outIdx + 3 >= endIdx) break;\n      if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).');\n      heap[outIdx++] = 0xF0 | (u >> 18);\n      heap[outIdx++] = 0x80 | ((u >> 12) & 63);\n      heap[outIdx++] = 0x80 | ((u >> 6) & 63);\n      heap[outIdx++] = 0x80 | (u & 63);\n    }\n  }\n  // Null-terminate the pointer to the buffer.\n  heap[outIdx] = 0;\n  return outIdx - startIdx;\n}\n\n/**\n * Copies the given Javascript String object 'str' to the emscripten HEAP at\n * address 'outPtr', null-terminated and encoded in UTF8 form. The copy will\n * require at most str.length*4+1 bytes of space in the HEAP.\n * Use the function lengthBytesUTF8 to compute the exact number of bytes\n * (excluding null terminator) that this function will write.\n *\n * @return {number} The number of bytes written, EXCLUDING the null terminator.\n */\nfunction stringToUTF8(str, outPtr, maxBytesToWrite) {\n  assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');\n  return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);\n}\n\n/**\n * Returns the number of bytes the given Javascript string takes if encoded as a\n * UTF8 byte array, EXCLUDING the null terminator byte.\n *\n * @param {string} str - JavaScript string to operator on\n * @return {number} Length, in bytes, of the UTF8 encoded string.\n */\nfunction lengthBytesUTF8(str) {\n  var len = 0;\n  for (var i = 0; i < str.length; ++i) {\n    // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code\n    // unit, not a Unicode code point of the character! So decode\n    // UTF16->UTF32->UTF8.\n    // See http://unicode.org/faq/utf_bom.html#utf16-3\n    var c = str.charCodeAt(i); // possibly a lead surrogate\n    if (c <= 0x7F) {\n      len++;\n    } else if (c <= 0x7FF) {\n      len += 2;\n    } else if (c >= 0xD800 && c <= 0xDFFF) {\n      len += 4; ++i;\n    } else {\n      len += 3;\n    }\n  }\n  return len;\n}\n\n// end include: runtime_strings.js\n// Memory management\n\nvar HEAP,\n/** @type {!Int8Array} */\n  HEAP8,\n/** @type {!Uint8Array} */\n  HEAPU8,\n/** @type {!Int16Array} */\n  HEAP16,\n/** @type {!Uint16Array} */\n  HEAPU16,\n/** @type {!Int32Array} */\n  HEAP32,\n/** @type {!Uint32Array} */\n  HEAPU32,\n/** @type {!Float32Array} */\n  HEAPF32,\n/** @type {!Float64Array} */\n  HEAPF64;\n\nfunction updateMemoryViews() {\n  var b = wasmMemory.buffer;\n  Module['HEAP8'] = HEAP8 = new Int8Array(b);\n  Module['HEAP16'] = HEAP16 = new Int16Array(b);\n  Module['HEAP32'] = HEAP32 = new Int32Array(b);\n  Module['HEAPU8'] = HEAPU8 = new Uint8Array(b);\n  Module['HEAPU16'] = HEAPU16 = new Uint16Array(b);\n  Module['HEAPU32'] = HEAPU32 = new Uint32Array(b);\n  Module['HEAPF32'] = HEAPF32 = new Float32Array(b);\n  Module['HEAPF64'] = HEAPF64 = new Float64Array(b);\n}\n\nvar STACK_SIZE = 65536;\nif (Module['STACK_SIZE']) assert(STACK_SIZE === Module['STACK_SIZE'], 'the stack size can no longer be determined at runtime')\n\nvar INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;legacyModuleProp('INITIAL_MEMORY', 'INITIAL_MEMORY');\n\nassert(INITIAL_MEMORY >= STACK_SIZE, 'INITIAL_MEMORY should be larger than STACK_SIZE, was ' + INITIAL_MEMORY + '! (STACK_SIZE=' + STACK_SIZE + ')');\n\n// check for full engine support (use string 'subarray' to avoid closure compiler confusion)\nassert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined,\n       'JS engine does not provide full typed array support');\n\n// If memory is defined in wasm, the user can't provide it.\nassert(!Module['wasmMemory'], 'Use of `wasmMemory` detected.  Use -sIMPORTED_MEMORY to define wasmMemory externally');\nassert(INITIAL_MEMORY == 16777216, 'Detected runtime INITIAL_MEMORY setting.  Use -sIMPORTED_MEMORY to define wasmMemory dynamically');\n\n// include: runtime_init_table.js\n// In regular non-RELOCATABLE mode the table is exported\n// from the wasm module and this will be assigned once\n// the exports are available.\nvar wasmTable;\n\n// end include: runtime_init_table.js\n// include: runtime_stack_check.js\n\n\n// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.\nfunction writeStackCookie() {\n  var max = _emscripten_stack_get_end();\n  assert((max & 3) == 0);\n  // If the stack ends at address zero we write our cookies 4 bytes into the\n  // stack.  This prevents interference with the (separate) address-zero check\n  // below.\n  if (max == 0) {\n    max += 4;\n  }\n  // The stack grow downwards towards _emscripten_stack_get_end.\n  // We write cookies to the final two words in the stack and detect if they are\n  // ever overwritten.\n  HEAPU32[((max)>>2)] = 0x2135467;\n  HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE;\n  // Also test the global address 0 for integrity.\n  HEAPU32[0] = 0x63736d65; /* 'emsc' */\n}\n\nfunction checkStackCookie() {\n  if (ABORT) return;\n  var max = _emscripten_stack_get_end();\n  // See writeStackCookie().\n  if (max == 0) {\n    max += 4;\n  }\n  var cookie1 = HEAPU32[((max)>>2)];\n  var cookie2 = HEAPU32[(((max)+(4))>>2)];\n  if (cookie1 != 0x2135467 || cookie2 != 0x89BACDFE) {\n    abort('Stack overflow! Stack cookie has been overwritten at ' + ptrToString(max) + ', expected hex dwords 0x89BACDFE and 0x2135467, but received ' + ptrToString(cookie2) + ' ' + ptrToString(cookie1));\n  }\n  // Also test the global address 0 for integrity.\n  if (HEAPU32[0] !== 0x63736d65 /* 'emsc' */) {\n    abort('Runtime error: The application has corrupted its heap memory area (address zero)!');\n  }\n}\n\n// end include: runtime_stack_check.js\n// include: runtime_assertions.js\n\n\n// Endianness check\n(function() {\n  var h16 = new Int16Array(1);\n  var h8 = new Int8Array(h16.buffer);\n  h16[0] = 0x6373;\n  if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)';\n})();\n\n// end include: runtime_assertions.js\nvar __ATPRERUN__  = []; // functions called before the runtime is initialized\nvar __ATINIT__    = []; // functions called during startup\nvar __ATMAIN__    = []; // functions called when main() is to be run\nvar __ATEXIT__    = []; // functions called during shutdown\nvar __ATPOSTRUN__ = []; // functions called after the main() is called\n\nvar runtimeInitialized = false;\n\nfunction keepRuntimeAlive() {\n  return noExitRuntime;\n}\n\nfunction preRun() {\n\n  if (Module['preRun']) {\n    if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];\n    while (Module['preRun'].length) {\n      addOnPreRun(Module['preRun'].shift());\n    }\n  }\n\n  callRuntimeCallbacks(__ATPRERUN__);\n}\n\nfunction initRuntime() {\n  assert(!runtimeInitialized);\n  runtimeInitialized = true;\n\n  checkStackCookie();\n\n  \n  callRuntimeCallbacks(__ATINIT__);\n}\n\nfunction preMain() {\n  checkStackCookie();\n  \n  callRuntimeCallbacks(__ATMAIN__);\n}\n\nfunction postRun() {\n  checkStackCookie();\n\n  if (Module['postRun']) {\n    if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];\n    while (Module['postRun'].length) {\n      addOnPostRun(Module['postRun'].shift());\n    }\n  }\n\n  callRuntimeCallbacks(__ATPOSTRUN__);\n}\n\nfunction addOnPreRun(cb) {\n  __ATPRERUN__.unshift(cb);\n}\n\nfunction addOnInit(cb) {\n  __ATINIT__.unshift(cb);\n}\n\nfunction addOnPreMain(cb) {\n  __ATMAIN__.unshift(cb);\n}\n\nfunction addOnExit(cb) {\n}\n\nfunction addOnPostRun(cb) {\n  __ATPOSTRUN__.unshift(cb);\n}\n\n// include: runtime_math.js\n\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc\n\nassert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');\nassert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');\nassert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');\nassert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');\n\n// end include: runtime_math.js\n// A counter of dependencies for calling run(). If we need to\n// do asynchronous work before running, increment this and\n// decrement it. Incrementing must happen in a place like\n// Module.preRun (used by emcc to add file preloading).\n// Note that you can add dependencies in preRun, even though\n// it happens right before run - run will be postponed until\n// the dependencies are met.\nvar runDependencies = 0;\nvar runDependencyWatcher = null;\nvar dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled\nvar runDependencyTracking = {};\n\nfunction getUniqueRunDependency(id) {\n  var orig = id;\n  while (1) {\n    if (!runDependencyTracking[id]) return id;\n    id = orig + Math.random();\n  }\n}\n\nfunction addRunDependency(id) {\n  runDependencies++;\n\n  if (Module['monitorRunDependencies']) {\n    Module['monitorRunDependencies'](runDependencies);\n  }\n\n  if (id) {\n    assert(!runDependencyTracking[id]);\n    runDependencyTracking[id] = 1;\n    if (runDependencyWatcher === null && typeof setInterval != 'undefined') {\n      // Check for missing dependencies every few seconds\n      runDependencyWatcher = setInterval(function() {\n        if (ABORT) {\n          clearInterval(runDependencyWatcher);\n          runDependencyWatcher = null;\n          return;\n        }\n        var shown = false;\n        for (var dep in runDependencyTracking) {\n          if (!shown) {\n            shown = true;\n            err('still waiting on run dependencies:');\n          }\n          err('dependency: ' + dep);\n        }\n        if (shown) {\n          err('(end of list)');\n        }\n      }, 10000);\n    }\n  } else {\n    err('warning: run dependency added without ID');\n  }\n}\n\nfunction removeRunDependency(id) {\n  runDependencies--;\n\n  if (Module['monitorRunDependencies']) {\n    Module['monitorRunDependencies'](runDependencies);\n  }\n\n  if (id) {\n    assert(runDependencyTracking[id]);\n    delete runDependencyTracking[id];\n  } else {\n    err('warning: run dependency removed without ID');\n  }\n  if (runDependencies == 0) {\n    if (runDependencyWatcher !== null) {\n      clearInterval(runDependencyWatcher);\n      runDependencyWatcher = null;\n    }\n    if (dependenciesFulfilled) {\n      var callback = dependenciesFulfilled;\n      dependenciesFulfilled = null;\n      callback(); // can add another dependenciesFulfilled\n    }\n  }\n}\n\n/** @param {string|number=} what */\nfunction abort(what) {\n  if (Module['onAbort']) {\n    Module['onAbort'](what);\n  }\n\n  what = 'Aborted(' + what + ')';\n  // TODO(sbc): Should we remove printing and leave it up to whoever\n  // catches the exception?\n  err(what);\n\n  ABORT = true;\n  EXITSTATUS = 1;\n\n  // Use a wasm runtime error, because a JS error might be seen as a foreign\n  // exception, which means we'd run destructors on it. We need the error to\n  // simply make the program stop.\n  // FIXME This approach does not work in Wasm EH because it currently does not assume\n  // all RuntimeErrors are from traps; it decides whether a RuntimeError is from\n  // a trap or not based on a hidden field within the object. So at the moment\n  // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that\n  // allows this in the wasm spec.\n\n  // Suppress closure compiler warning here. Closure compiler's builtin extern\n  // defintion for WebAssembly.RuntimeError claims it takes no arguments even\n  // though it can.\n  // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.\n  /** @suppress {checkTypes} */\n  var e = new WebAssembly.RuntimeError(what);\n\n  // Throw the error whether or not MODULARIZE is set because abort is used\n  // in code paths apart from instantiation where an exception is expected\n  // to be thrown when abort is called.\n  throw e;\n}\n\n// {{MEM_INITIALIZER}}\n\n// include: memoryprofiler.js\n\n\n// end include: memoryprofiler.js\n// show errors on likely calls to FS when it was not included\nvar FS = {\n  error: function() {\n    abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -sFORCE_FILESYSTEM');\n  },\n  init: function() { FS.error() },\n  createDataFile: function() { FS.error() },\n  createPreloadedFile: function() { FS.error() },\n  createLazyFile: function() { FS.error() },\n  open: function() { FS.error() },\n  mkdev: function() { FS.error() },\n  registerDevice: function() { FS.error() },\n  analyzePath: function() { FS.error() },\n  loadFilesFromDB: function() { FS.error() },\n\n  ErrnoError: function ErrnoError() { FS.error() },\n};\nModule['FS_createDataFile'] = FS.createDataFile;\nModule['FS_createPreloadedFile'] = FS.createPreloadedFile;\n\n// include: URIUtils.js\n\n\n// Prefix of data URIs emitted by SINGLE_FILE and related options.\nvar dataURIPrefix = 'data:application/octet-stream;base64,';\n\n// Indicates whether filename is a base64 data URI.\nfunction isDataURI(filename) {\n  // Prefix of data URIs emitted by SINGLE_FILE and related options.\n  return filename.startsWith(dataURIPrefix);\n}\n\n// Indicates whether filename is delivered via file protocol (as opposed to http/https)\nfunction isFileURI(filename) {\n  return filename.startsWith('file://');\n}\n\n// end include: URIUtils.js\n/** @param {boolean=} fixedasm */\nfunction createExportWrapper(name, fixedasm) {\n  return function() {\n    var displayName = name;\n    var asm = fixedasm;\n    if (!fixedasm) {\n      asm = Module['asm'];\n    }\n    assert(runtimeInitialized, 'native function `' + displayName + '` called before runtime initialization');\n    if (!asm[name]) {\n      assert(asm[name], 'exported native function `' + displayName + '` not found');\n    }\n    return asm[name].apply(null, arguments);\n  };\n}\n\nvar wasmBinaryFile;\n  wasmBinaryFile = 'wolf.wasm';\n  if (!isDataURI(wasmBinaryFile)) {\n    wasmBinaryFile = locateFile(wasmBinaryFile);\n  }\n\nfunction getBinary(file) {\n  try {\n    if (file == wasmBinaryFile && wasmBinary) {\n      return new Uint8Array(wasmBinary);\n    }\n    if (readBinary) {\n      return readBinary(file);\n    }\n    throw \"both async and sync fetching of the wasm failed\";\n  }\n  catch (err) {\n    abort(err);\n  }\n}\n\nfunction getBinaryPromise() {\n  // If we don't have the binary yet, try to to load it asynchronously.\n  // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.\n  // See https://github.com/github/fetch/pull/92#issuecomment-140665932\n  // Cordova or Electron apps are typically loaded from a file:// url.\n  // So use fetch if it is available and the url is not a file, otherwise fall back to XHR.\n  if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {\n    if (typeof fetch == 'function'\n      && !isFileURI(wasmBinaryFile)\n    ) {\n      return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {\n        if (!response['ok']) {\n          throw \"failed to load wasm binary file at '\" + wasmBinaryFile + \"'\";\n        }\n        return response['arrayBuffer']();\n      }).catch(function () {\n          return getBinary(wasmBinaryFile);\n      });\n    }\n    else {\n      if (readAsync) {\n        // fetch is not available or url is file => try XHR (readAsync uses XHR internally)\n        return new Promise(function(resolve, reject) {\n          readAsync(wasmBinaryFile, function(response) { resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))) }, reject)\n        });\n      }\n    }\n  }\n\n  // Otherwise, getBinary should be able to get it synchronously\n  return Promise.resolve().then(function() { return getBinary(wasmBinaryFile); });\n}\n\n// Create the wasm instance.\n// Receives the wasm imports, returns the exports.\nfunction createWasm() {\n  // prepare imports\n  var info = {\n    'env': asmLibraryArg,\n    'wasi_snapshot_preview1': asmLibraryArg,\n  };\n  // Load the wasm module and create an instance of using native support in the JS engine.\n  // handle a generated wasm instance, receiving its exports and\n  // performing other necessary setup\n  /** @param {WebAssembly.Module=} module*/\n  function receiveInstance(instance, module) {\n    var exports = instance.exports;\n\n    Module['asm'] = exports;\n\n    wasmMemory = Module['asm']['memory'];\n    assert(wasmMemory, \"memory not found in wasm exports\");\n    // This assertion doesn't hold when emscripten is run in --post-link\n    // mode.\n    // TODO(sbc): Read INITIAL_MEMORY out of the wasm file in post-link mode.\n    //assert(wasmMemory.buffer.byteLength === 16777216);\n    updateMemoryViews();\n\n    wasmTable = Module['asm']['__indirect_function_table'];\n    assert(wasmTable, \"table not found in wasm exports\");\n\n    addOnInit(Module['asm']['__wasm_call_ctors']);\n\n    removeRunDependency('wasm-instantiate');\n\n  }\n  // wait for the pthread pool (if any)\n  addRunDependency('wasm-instantiate');\n\n  // Prefer streaming instantiation if available.\n  // Async compilation can be confusing when an error on the page overwrites Module\n  // (for example, if the order of elements is wrong, and the one defining Module is\n  // later), so we save Module and check it later.\n  var trueModule = Module;\n  function receiveInstantiationResult(result) {\n    // 'result' is a ResultObject object which has both the module and instance.\n    // receiveInstance() will swap in the exports (to Module.asm) so they can be called\n    assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');\n    trueModule = null;\n    // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.\n    // When the regression is fixed, can restore the above USE_PTHREADS-enabled path.\n    receiveInstance(result['instance']);\n  }\n\n  function instantiateArrayBuffer(receiver) {\n    return getBinaryPromise().then(function(binary) {\n      return WebAssembly.instantiate(binary, info);\n    }).then(function (instance) {\n      return instance;\n    }).then(receiver, function(reason) {\n      err('failed to asynchronously prepare wasm: ' + reason);\n\n      // Warn on some common problems.\n      if (isFileURI(wasmBinaryFile)) {\n        err('warning: Loading from a file URI (' + wasmBinaryFile + ') is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing');\n      }\n      abort(reason);\n    });\n  }\n\n  function instantiateAsync() {\n    if (!wasmBinary &&\n        typeof WebAssembly.instantiateStreaming == 'function' &&\n        !isDataURI(wasmBinaryFile) &&\n        // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.\n        !isFileURI(wasmBinaryFile) &&\n        // Avoid instantiateStreaming() on Node.js environment for now, as while\n        // Node.js v18.1.0 implements it, it does not have a full fetch()\n        // implementation yet.\n        //\n        // Reference:\n        //   https://github.com/emscripten-core/emscripten/pull/16917\n        !ENVIRONMENT_IS_NODE &&\n        typeof fetch == 'function') {\n      return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {\n        // Suppress closure warning here since the upstream definition for\n        // instantiateStreaming only allows Promise<Repsponse> rather than\n        // an actual Response.\n        // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.\n        /** @suppress {checkTypes} */\n        var result = WebAssembly.instantiateStreaming(response, info);\n\n        return result.then(\n          receiveInstantiationResult,\n          function(reason) {\n            // We expect the most common failure cause to be a bad MIME type for the binary,\n            // in which case falling back to ArrayBuffer instantiation should work.\n            err('wasm streaming compile failed: ' + reason);\n            err('falling back to ArrayBuffer instantiation');\n            return instantiateArrayBuffer(receiveInstantiationResult);\n          });\n      });\n    } else {\n      return instantiateArrayBuffer(receiveInstantiationResult);\n    }\n  }\n\n  // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback\n  // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel\n  // to any other async startup actions they are performing.\n  // Also pthreads and wasm workers initialize the wasm instance through this path.\n  if (Module['instantiateWasm']) {\n    try {\n      var exports = Module['instantiateWasm'](info, receiveInstance);\n      return exports;\n    } catch(e) {\n      err('Module.instantiateWasm callback failed with error: ' + e);\n        return false;\n    }\n  }\n\n  instantiateAsync();\n  return {}; // no exports yet; we'll fill them in later\n}\n\n// Globals used by JS i64 conversions (see makeSetValue)\nvar tempDouble;\nvar tempI64;\n\n// === Body ===\n\nvar ASM_CONSTS = {\n  86684: ($0) => { var _debug = \"\"; if ($0 === 1) { _debug = \"all\"; } Janus.init({ debug: _debug , callback: function () { if (!Janus.isWebrtcSupported()) { console.error(\"No WebRTC support\"); return 1; } } }); capture = null; id = null; local_tracks = {}; local_videos = 0; remote_tracks = {}; remote_videos = 0; role = null; room = null; screen = null; source = null; spinner = null; var _char_set = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; opaque_id = \"\"; for (var i = 0; i < 11; i++) { var _random_pos = Math.floor(Math.random() * _char_set.length); opaque_id += _char_set.substring(_random_pos, _random_pos + 1); } janus = new Janus({ server: server, iceServers: ice_servers, success: function () { janus.attach( { plugin: \"janus.plugin.videoroom\", opaqueId: opaque_id, success: function (p_plugin_handle) { screen = p_plugin_handle; Janus.log(\"plugin attached! (\" + screen.getPlugin() + \", id=\" + screen.getId() + \")\"); _on_init_callback(0); }, error: function (p_error) { Janus.error(\"error attaching plugin: \", p_error); _on_init_callback(1); }, consentDialog: function (p_on) { Janus.debug(\"consent dialog should be \" + (p_on ? \"on\" : \"off\") + \" now\"); }, iceState: function (p_state) { Janus.log(\"ICE state changed to \" + p_state); }, mediaState: function (p_medium, p_on, p_mid) { Janus.log(\"Janus \" + (p_on ? \"started\" : \"stopped\") + \" receiving our \" + p_medium + \" (mid=\" + p_mid + \")\"); }, webrtcState: function (p_on) { Janus.log(\"Janus WebRTC peer connection is \" + (p_on ? \"up\" : \"down\") + \" now\"); $(\"#streamscreen\").parent().parent().unblock(); if (p_on) { Janus.log(\"your screen sharing session just started: pass the \\\"\" + room + \"\\\" session identifier to those who want to attend.\"); _on_screen_shared(room); } else { Janus.log(\"your screen sharing session just stopped\"); janus.destroy(); } }, slowLink: function (p_uplink, p_lost, p_mid) { Janus.log(\"Janus reports problems \" + (p_uplink ? \"sending\" : \"receiving\") + \" packets on mid \" + p_mid + \" (\" + p_lost + \" lost packets)\"); }, onmessage: function (p_msg, p_jsep) { Janus.debug(\"got a message (publisher): \", p_msg); var _event = p_msg[\"videoroom\"]; Janus.debug(\"event: \" + _event); if (_event) { if (_event === \"joined\") { id = p_msg[\"id\"]; Janus.log(\"successfully joined room \" + p_msg[\"room\"] + \" with ID \" + id); if (role === \"publisher\") { Janus.debug(\"negotiating WebRTC stream for our screen (capture \" + capture + \")\"); if (Janus.webRTCAdapter.browserDetails.browser === \"safari\") { window.alert(\"Safari requires a user gesture before the screen can be shared: close this dialog to do that\"); screen.createOffer( { tracks: [ { type: 'audio', capture: true, recv: false }, { type: 'screen', capture: true, recv: false } ], success: function (p_jsep) { Janus.debug(\"Got publisher SDP!\", p_jsep); var _publish = { request: \"configure\", audio: true, video: true }; screen.send({ message: _publish, jsep: p_jsep }); }, error: function (p_error) { Janus.error(\"WebRTC error:\", p_error.message); } }); } else { screen.createOffer( { tracks: [ { type: 'audio', capture: true, recv: false }, { type: 'screen', capture: true, recv: false } ], success: function (p_jsep) { Janus.debug(\"got publisher SDP!\", p_jsep); var _publish = { request: \"configure\", audio: true, video: true }; screen.send({ message: _publish, jsep: p_jsep }); }, error: function (p_error) { Janus.error(\"WebRTC error:\", p_error); } }); } } else { if (p_msg[\"publishers\"]) { var _list = p_msg[\"publishers\"]; Janus.debug(\"got a list of available publishers/feeds:\", _list); for (var f in _list) { if (_list[f][\"dummy\"]) continue; var _id = _list[f][\"id\"]; var _display = _list[f][\"display\"]; Janus.debug(\"  >> [\" + _id + \"] \" + _display); new_remote_feed(_id, _display) } } } } else if (_event === \"event\") { if (role === \"listener\" && p_msg[\"publishers\"]) { var _list = p_msg[\"publishers\"]; Janus.debug(\"got a list of available publishers/feeds:\", _list); for (var f in _list) { if (_list[f][\"dummy\"]) continue; var _id = _list[f][\"id\"]; var _display = _list[f][\"display\"]; Janus.debug(\"  >> [\" + _id + \"] \" + _display); new_remote_feed(_id, _display) } } else if (p_msg[\"leaving\"]) { var _leaving = p_msg[\"leaving\"]; Janus.log(\"publisher left: \" + _leaving); if (role === \"listener\" && p_msg[\"leaving\"] === source) { Janus.error(\"the screen sharing session is over, the publisher left\"); } } else if (p_msg[\"error\"]) { Janus.error(p_msg[\"error\"]); } } } if (p_jsep) { Janus.debug(\"handling SDP as well \", p_jsep); screen.handleRemoteJsep({ jsep: p_jsep }); } }, onlocaltrack: function (p_track, p_on) { Janus.debug(\"local track \" + (p_on ? \"added\" : \"removed\") + \":\", p_track); var _track_id = p_track.id.replace(/[{}]/g, \"\"); if (!p_on) { var _stream = local_tracks[_track_id]; if (_stream) { try { var _tracks = _stream.getTracks(); for (var _t in _tracks) { var _mst = _tracks[_t]; if (_mst) { _mst.stop(); } } } catch (p_e) { } } if (p_track.kind === \"video\") { $('#screenvideo' + _track_id).remove(); local_videos--; if (local_videos === 0) { if ($('#streamscreen .no-video-container').length === 0) { Janus.log(\"No webcam available\"); } } } delete local_tracks[_track_id]; return; } var _stream = local_tracks[_track_id]; if (_stream) { return; } if (p_track.kind === \"audio\") { if (local_videos === 0) { if ($('#streamscreen .no-video-container').length === 0) { Janus.log(\"No webcam available\"); } } } else { local_videos++; $('#streamscreen .no-video-container').remove(); _stream = new MediaStream([p_track]); local_tracks[_track_id] = _stream; Janus.log(\"Created local stream:\", _stream); $('#streamscreen').append('<video muted=\"muted\" id=\"screenvideo' + _track_id + '\" width=100% autoplay playsinline muted=\"muted\"/>'); Janus.attachMediaStream($('#screenvideo' + _track_id).get(0), _stream); } if (screen.webrtcStuff.pc.iceConnectionState !== \"completed\" && screen.webrtcStuff.pc.iceConnectionState !== \"connected\") { $(\"#streamscreen\").parent().parent().block({ message: '<b>Publishing...</b>', css: { border: 'none', backgroundColor: 'transparent', color: 'white' } }); } }, onremotetrack: function (track, mid, on) { }, oncleanup: function () { Janus.log(\"got a cleanup notification\"); $('#streamscreen').empty(); $(\"#streamscreen\").parent().unblock(); local_tracks = {}; local_videos = 0; } }); }, error: function (error) { Janus.error(error); }, destroyed: function () { Janus.log(\"Janus session id:\" + id + \" destroyed\"); } }); new_remote_feed = function (p_id, p_display) { source = p_id; var _remote_feed = null; janus.attach({ plugin: \"janus.plugin.videoroom\", opaqueId: opaque_id, success: function (p_plugin_handle) { _remote_feed = p_plugin_handle; _remote_feed.remote_tracks = {}; _remote_feed.remote_videos = 0; Janus.log(\"plugin attached! (\" + _remote_feed.getPlugin() + \", id=\" + _remote_feed.getId() + \")\"); Janus.log(\"this is a subscriber\"); var _listen = { request: \"join\", room: room, ptype: \"subscriber\", feed: p_id }; _remote_feed.send({ message: _listen }); }, error: function (p_error) { Janus.error(\"error attaching plugin: \", p_error); }, iceState: function (p_state) { Janus.log(\"ICE state (feed #\" + _remote_feed.rfindex + \") changed to \" + p_state); }, webrtcState: function (p_on) { Janus.log(\"Janus says this WebRTC PeerConnection (feed #\" + _remote_feed.rfindex + \") is \" + (p_on ? \"up\" : \"down\") + \" now\"); }, slowLink: function (p_uplink, p_lost, p_mid) { Janus.warn(\"Janus reports problems \" + (p_uplink ? \"sending\" : \"receiving\") + \" packets on mid \" + p_mid + \" (\" + p_lost + \" lost packets)\"); }, onmessage: function (p_msg, p_jsep) { Janus.debug(\"got a message (listener): \", p_msg); var _event = p_msg[\"videoroom\"]; Janus.debug(\"Janus event: \" + _event); if (_event) { if (_event === \"attached\") { if (!spinner) { var _target = document.getElementById('#streamscreen'); spinner = new Spinner({ top: 100 }).spin(_target); } else { spinner.spin(); } Janus.log(\"successfully attached to feed \" + id + \" (\" + p_display + \") in room \" + p_msg[\"room\"]); } } if (p_jsep) { Janus.debug(\"handling SDP as well: \", p_jsep); _remote_feed.createAnswer( { jsep: p_jsep, tracks: [ { type: 'data' } ], success: function (p_jsep) { Janus.debug(\"got SDP!\", p_jsep); var _body = { request: \"start\", room: room }; _remote_feed.send({ message: _body, jsep: p_jsep }); }, error: function (p_error) { Janus.error(\"WebRTC error:\", p_error); } }); } }, onlocaltrack: function (p_track, p_on) { }, onremotetrack: function (p_track, p_mid, p_on) { Janus.debug(\"remote track (mid=\" + p_mid + \") \" + (p_on ? \"added\" : \"removed\") + \":\", p_track); if (!p_on) { $('#screenvideo' + p_mid).remove(); if (p_track.kind === \"video\") { remote_videos--; if (remote_videos === 0) { if ($('#streamscreen .no-video-container').length === 0) { Janus.log(\"no remote video available\"); } } } delete remote_tracks[p_mid]; return; } if (spinner !== undefined && spinner !== null) { spinner.stop(); spinner = null; } if (p_track.kind === \"audio\") { _stream = new MediaStream([p_track]); remote_tracks[p_mid] = _stream; Janus.log(\"created remote audio stream:\", _stream); $('#streamscreen').append('<audio hidden id=\"screenvideo' + p_mid + '\" playsinline/>'); $('#screenvideo' + p_mid).get(0).volume = 0; Janus.attachMediaStream($('#screenvideo' + p_mid).get(0), _stream); var _play_promise = $('#screenvideo' + p_mid).get(0).play(); if (_play_promise !== undefined) { _play_promise.then(_ => { $('#screenvideo' + p_mid).get(0).volume = 1; }) .catch(p_error => { }); } if (remote_videos === 0) { if ($('#streamscreen .no-video-container').length === 0) { Janus.log(\"no remote video available\"); } } } else { remote_videos++; $('#streamscreen .no-video-container').remove(); _stream = new MediaStream([p_track]); _remote_feed.remote_tracks[p_mid] = _stream; Janus.log(\"created remote video stream:\", _stream); $('#streamscreen').append('<video muted id=\"screenvideo' + p_mid + '\" width=100% playsinline/>'); $('#screenvideo' + p_mid).get(0).volume = 0; Janus.attachMediaStream($('#screenvideo' + p_mid).get(0), _stream); var _play_promise = $('#screenvideo' + p_mid).get(0).play(); if (_play_promise !== undefined) { _play_promise.then(_ => { $('#screenvideo' + p_mid).get(0).volume = 1; }) .catch(p_error => { }); } } }, oncleanup: function () { Janus.log(\"got a cleanup notification (remote feed \" + p_id + \")\"); $('#waitingvideo').remove(); if (spinner) { spinner.stop(); } spinner = null; _remote_feed.remote_tracks = {}; _remote_feed.remote_videos = 0; } }); }; return 0; },  \n 97125: ($0, $1, $2) => { if (!Janus.isExtensionEnabled()) { Janus.error(\"this browser doesn't support screensharing (getDisplayMedia unavailable)\"); return; } capture = \"screen\"; var _desc = \"\" + UTF8ToString($1); role = \"publisher\"; var create = {}; create.request= \"create\"; createdescription= _desc; create.bitrate= $2; createpublishers= 1; screen.send({ message: create, success: function (p_result) { if (p_result[\"error\"]) { Janus.error(\"couldn't create room: \" + p_result[\"error\"]); return; } var _event = p_result[\"videoroom\"]; Janus.debug(\"Event: \" + _event); if (_event) { room = p_result[\"room\"]; Janus.log(\"screen sharing session created: \" + room); var _username = \"\" + UTF8ToString($0); var _register = { request: \"join\", room: room, ptype: \"publisher\", display: _username }; screen.send({ message: _register }); } } }); return 0; },  \n 97949: ($0, $1) => { room = $0; role = \"listener\"; var _username = \"\" + UTF8ToString($1); var _register = {}; _register.request= \"join\"; _register.room= room; _register.ptype= \"publisher\"; _register.display= _username; screen.send({ message: _register }); return 0; }\n};\n\n\n\n\n\n  /** @constructor */\n  function ExitStatus(status) {\n      this.name = 'ExitStatus';\n      this.message = 'Program terminated with exit(' + status + ')';\n      this.status = status;\n    }\n\n  function callRuntimeCallbacks(callbacks) {\n      while (callbacks.length > 0) {\n        // Pass the module as the first argument.\n        callbacks.shift()(Module);\n      }\n    }\n\n  \n    /**\n     * @param {number} ptr\n     * @param {string} type\n     */\n  function getValue(ptr, type = 'i8') {\n      if (type.endsWith('*')) type = '*';\n      switch (type) {\n        case 'i1': return HEAP8[((ptr)>>0)];\n        case 'i8': return HEAP8[((ptr)>>0)];\n        case 'i16': return HEAP16[((ptr)>>1)];\n        case 'i32': return HEAP32[((ptr)>>2)];\n        case 'i64': return HEAP32[((ptr)>>2)];\n        case 'float': return HEAPF32[((ptr)>>2)];\n        case 'double': return HEAPF64[((ptr)>>3)];\n        case '*': return HEAPU32[((ptr)>>2)];\n        default: abort('invalid type for getValue: ' + type);\n      }\n      return null;\n    }\n\n  function ptrToString(ptr) {\n      assert(typeof ptr === 'number');\n      return '0x' + ptr.toString(16).padStart(8, '0');\n    }\n\n  \n    /**\n     * @param {number} ptr\n     * @param {number} value\n     * @param {string} type\n     */\n  function setValue(ptr, value, type = 'i8') {\n      if (type.endsWith('*')) type = '*';\n      switch (type) {\n        case 'i1': HEAP8[((ptr)>>0)] = value; break;\n        case 'i8': HEAP8[((ptr)>>0)] = value; break;\n        case 'i16': HEAP16[((ptr)>>1)] = value; break;\n        case 'i32': HEAP32[((ptr)>>2)] = value; break;\n        case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math.min((+(Math.floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)] = tempI64[0],HEAP32[(((ptr)+(4))>>2)] = tempI64[1]); break;\n        case 'float': HEAPF32[((ptr)>>2)] = value; break;\n        case 'double': HEAPF64[((ptr)>>3)] = value; break;\n        case '*': HEAPU32[((ptr)>>2)] = value; break;\n        default: abort('invalid type for setValue: ' + type);\n      }\n    }\n\n  function warnOnce(text) {\n      if (!warnOnce.shown) warnOnce.shown = {};\n      if (!warnOnce.shown[text]) {\n        warnOnce.shown[text] = 1;\n        if (ENVIRONMENT_IS_NODE) text = 'warning: ' + text;\n        err(text);\n      }\n    }\n\n  function ___assert_fail(condition, filename, line, func) {\n      abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);\n    }\n\n  var exceptionCaught =  [];\n  \n  function exception_addRef(info) {\n      info.add_ref();\n    }\n  \n  var uncaughtExceptionCount = 0;\n  function ___cxa_begin_catch(ptr) {\n      var info = new ExceptionInfo(ptr);\n      if (!info.get_caught()) {\n        info.set_caught(true);\n        uncaughtExceptionCount--;\n      }\n      info.set_rethrown(false);\n      exceptionCaught.push(info);\n      exception_addRef(info);\n      return info.get_exception_ptr();\n    }\n\n  \n  var exceptionLast = 0;\n  \n  \n  var wasmTableMirror = [];\n  \n  function getWasmTableEntry(funcPtr) {\n      var func = wasmTableMirror[funcPtr];\n      if (!func) {\n        if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;\n        wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);\n      }\n      assert(wasmTable.get(funcPtr) == func, \"JavaScript-side Wasm function table mirror is out of date!\");\n      return func;\n    }\n  function exception_decRef(info) {\n      // A rethrown exception can reach refcount 0; it must not be discarded\n      // Its next handler will clear the rethrown flag and addRef it, prior to\n      // final decRef and destruction here\n      if (info.release_ref() && !info.get_rethrown()) {\n        var destructor = info.get_destructor();\n        if (destructor) {\n          // In Wasm, destructors return 'this' as in ARM\n          getWasmTableEntry(destructor)(info.excPtr);\n        }\n        ___cxa_free_exception(info.excPtr);\n      }\n    }\n  function ___cxa_end_catch() {\n      // Clear state flag.\n      _setThrew(0);\n      assert(exceptionCaught.length > 0);\n      // Call destructor if one is registered then clear it.\n      var info = exceptionCaught.pop();\n  \n      exception_decRef(info);\n      exceptionLast = 0; // XXX in decRef?\n    }\n\n  \n  /** @constructor */\n  function ExceptionInfo(excPtr) {\n      this.excPtr = excPtr;\n      this.ptr = excPtr - 24;\n  \n      this.set_type = function(type) {\n        HEAPU32[(((this.ptr)+(4))>>2)] = type;\n      };\n  \n      this.get_type = function() {\n        return HEAPU32[(((this.ptr)+(4))>>2)];\n      };\n  \n      this.set_destructor = function(destructor) {\n        HEAPU32[(((this.ptr)+(8))>>2)] = destructor;\n      };\n  \n      this.get_destructor = function() {\n        return HEAPU32[(((this.ptr)+(8))>>2)];\n      };\n  \n      this.set_refcount = function(refcount) {\n        HEAP32[((this.ptr)>>2)] = refcount;\n      };\n  \n      this.set_caught = function (caught) {\n        caught = caught ? 1 : 0;\n        HEAP8[(((this.ptr)+(12))>>0)] = caught;\n      };\n  \n      this.get_caught = function () {\n        return HEAP8[(((this.ptr)+(12))>>0)] != 0;\n      };\n  \n      this.set_rethrown = function (rethrown) {\n        rethrown = rethrown ? 1 : 0;\n        HEAP8[(((this.ptr)+(13))>>0)] = rethrown;\n      };\n  \n      this.get_rethrown = function () {\n        return HEAP8[(((this.ptr)+(13))>>0)] != 0;\n      };\n  \n      // Initialize native structure fields. Should be called once after allocated.\n      this.init = function(type, destructor) {\n        this.set_adjusted_ptr(0);\n        this.set_type(type);\n        this.set_destructor(destructor);\n        this.set_refcount(0);\n        this.set_caught(false);\n        this.set_rethrown(false);\n      }\n  \n      this.add_ref = function() {\n        var value = HEAP32[((this.ptr)>>2)];\n        HEAP32[((this.ptr)>>2)] = value + 1;\n      };\n  \n      // Returns true if last reference released.\n      this.release_ref = function() {\n        var prev = HEAP32[((this.ptr)>>2)];\n        HEAP32[((this.ptr)>>2)] = prev - 1;\n        assert(prev > 0);\n        return prev === 1;\n      };\n  \n      this.set_adjusted_ptr = function(adjustedPtr) {\n        HEAPU32[(((this.ptr)+(16))>>2)] = adjustedPtr;\n      };\n  \n      this.get_adjusted_ptr = function() {\n        return HEAPU32[(((this.ptr)+(16))>>2)];\n      };\n  \n      // Get pointer which is expected to be received by catch clause in C++ code. It may be adjusted\n      // when the pointer is casted to some of the exception object base classes (e.g. when virtual\n      // inheritance is used). When a pointer is thrown this method should return the thrown pointer\n      // itself.\n      this.get_exception_ptr = function() {\n        // Work around a fastcomp bug, this code is still included for some reason in a build without\n        // exceptions support.\n        var isPointer = ___cxa_is_pointer_type(this.get_type());\n        if (isPointer) {\n          return HEAPU32[((this.excPtr)>>2)];\n        }\n        var adjusted = this.get_adjusted_ptr();\n        if (adjusted !== 0) return adjusted;\n        return this.excPtr;\n      };\n    }\n  \n  function ___resumeException(ptr) {\n      if (!exceptionLast) { exceptionLast = ptr; }\n      throw ptr + \" - Exception catching is disabled, this exception cannot be caught. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.\";\n    }\n  \n  \n  function ___cxa_find_matching_catch_2() {\n      var thrown = exceptionLast;\n      if (!thrown) {\n        // just pass through the null ptr\n        setTempRet0(0);\n        return 0;\n      }\n      var info = new ExceptionInfo(thrown);\n      info.set_adjusted_ptr(thrown);\n      var thrownType = info.get_type();\n      if (!thrownType) {\n        // just pass through the thrown ptr\n        setTempRet0(0);\n        return thrown;\n      }\n  \n      // can_catch receives a **, add indirection\n      // The different catch blocks are denoted by different types.\n      // Due to inheritance, those types may not precisely match the\n      // type of the thrown object. Find one which matches, and\n      // return the type of the catch block which should be called.\n      for (var i = 0; i < arguments.length; i++) {\n        var caughtType = arguments[i];\n        if (caughtType === 0 || caughtType === thrownType) {\n          // Catch all clause matched or exactly the same type is caught\n          break;\n        }\n        var adjusted_ptr_addr = info.ptr + 16;\n        if (___cxa_can_catch(caughtType, thrownType, adjusted_ptr_addr)) {\n          setTempRet0(caughtType);\n          return thrown;\n        }\n      }\n      setTempRet0(thrownType);\n      return thrown;\n    }\n\n  \n  \n  \n  \n  function ___cxa_find_matching_catch_3() {\n      var thrown = exceptionLast;\n      if (!thrown) {\n        // just pass through the null ptr\n        setTempRet0(0);\n        return 0;\n      }\n      var info = new ExceptionInfo(thrown);\n      info.set_adjusted_ptr(thrown);\n      var thrownType = info.get_type();\n      if (!thrownType) {\n        // just pass through the thrown ptr\n        setTempRet0(0);\n        return thrown;\n      }\n  \n      // can_catch receives a **, add indirection\n      // The different catch blocks are denoted by different types.\n      // Due to inheritance, those types may not precisely match the\n      // type of the thrown object. Find one which matches, and\n      // return the type of the catch block which should be called.\n      for (var i = 0; i < arguments.length; i++) {\n        var caughtType = arguments[i];\n        if (caughtType === 0 || caughtType === thrownType) {\n          // Catch all clause matched or exactly the same type is caught\n          break;\n        }\n        var adjusted_ptr_addr = info.ptr + 16;\n        if (___cxa_can_catch(caughtType, thrownType, adjusted_ptr_addr)) {\n          setTempRet0(caughtType);\n          return thrown;\n        }\n      }\n      setTempRet0(thrownType);\n      return thrown;\n    }\n\n  \n  \n  function ___cxa_throw(ptr, type, destructor) {\n      var info = new ExceptionInfo(ptr);\n      // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception.\n      info.init(type, destructor);\n      exceptionLast = ptr;\n      uncaughtExceptionCount++;\n      throw ptr + \" - Exception catching is disabled, this exception cannot be caught. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.\";\n    }\n\n\n  function _abort() {\n      abort('native code called abort()');\n    }\n\n  var readEmAsmArgsArray = [];\n  function readEmAsmArgs(sigPtr, buf) {\n      // Nobody should have mutated _readEmAsmArgsArray underneath us to be something else than an array.\n      assert(Array.isArray(readEmAsmArgsArray));\n      // The input buffer is allocated on the stack, so it must be stack-aligned.\n      assert(buf % 16 == 0);\n      readEmAsmArgsArray.length = 0;\n      var ch;\n      // Most arguments are i32s, so shift the buffer pointer so it is a plain\n      // index into HEAP32.\n      buf >>= 2;\n      while (ch = HEAPU8[sigPtr++]) {\n        var chr = String.fromCharCode(ch);\n        var validChars = ['d', 'f', 'i'];\n        assert(validChars.includes(chr), 'Invalid character ' + ch + '(\"' + chr + '\") in readEmAsmArgs! Use only [' + validChars + '], and do not specify \"v\" for void return argument.');\n        // Floats are always passed as doubles, and doubles and int64s take up 8\n        // bytes (two 32-bit slots) in memory, align reads to these:\n        buf += (ch != 105/*i*/) & buf;\n        readEmAsmArgsArray.push(\n          ch == 105/*i*/ ? HEAP32[buf] :\n         HEAPF64[buf++ >> 1]\n        );\n        ++buf;\n      }\n      return readEmAsmArgsArray;\n    }\n  function runEmAsmFunction(code, sigPtr, argbuf) {\n      var args = readEmAsmArgs(sigPtr, argbuf);\n      if (!ASM_CONSTS.hasOwnProperty(code)) abort('No EM_ASM constant found at address ' + code);\n      return ASM_CONSTS[code].apply(null, args);\n    }\n  function _emscripten_asm_const_int(code, sigPtr, argbuf) {\n      return runEmAsmFunction(code, sigPtr, argbuf);\n    }\n\n  function reallyNegative(x) {\n      return x < 0 || (x === 0 && (1/x) === -Infinity);\n    }\n  \n  function convertI32PairToI53(lo, hi) {\n      // This function should not be getting called with too large unsigned numbers\n      // in high part (if hi >= 0x7FFFFFFFF, one should have been calling\n      // convertU32PairToI53())\n      assert(hi === (hi|0));\n      return (lo >>> 0) + hi * 4294967296;\n    }\n  \n  function convertU32PairToI53(lo, hi) {\n      return (lo >>> 0) + (hi >>> 0) * 4294967296;\n    }\n  \n  function reSign(value, bits) {\n      if (value <= 0) {\n        return value;\n      }\n      var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32\n                            : Math.pow(2, bits-1);\n      // for huge values, we can hit the precision limit and always get true here.\n      // so don't do that but, in general there is no perfect solution here. With\n      // 64-bit ints, we get rounding and errors\n      // TODO: In i64 mode 1, resign the two parts separately and safely\n      if (value >= half && (bits <= 32 || value > half)) {\n        // Cannot bitshift half, as it may be at the limit of the bits JS uses in\n        // bitshifts\n        value = -2*half + value;\n      }\n      return value;\n    }\n  \n  function unSign(value, bits) {\n      if (value >= 0) {\n        return value;\n      }\n      // Need some trickery, since if bits == 32, we are right at the limit of the\n      // bits JS uses in bitshifts\n      return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value\n                        : Math.pow(2, bits)         + value;\n    }\n  \n  function strLen(ptr) {\n      var end = ptr;\n      while (HEAPU8[end]) ++end;\n      return end - ptr;\n    }\n  \n  /** @type {function(string, boolean=, number=)} */\n  function intArrayFromString(stringy, dontAddNull, length) {\n    var len = length > 0 ? length : lengthBytesUTF8(stringy)+1;\n    var u8array = new Array(len);\n    var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);\n    if (dontAddNull) u8array.length = numBytesWritten;\n    return u8array;\n  }\n  function formatString(format, varargs) {\n      assert((varargs & 3) === 0);\n      var textIndex = format;\n      var argIndex = varargs;\n      // This must be called before reading a double or i64 vararg. It will bump the pointer properly.\n      // It also does an assert on i32 values, so it's nice to call it before all varargs calls.\n      function prepVararg(ptr, type) {\n        if (type === 'double' || type === 'i64') {\n          // move so the load is aligned\n          if (ptr & 7) {\n            assert((ptr & 7) === 4);\n            ptr += 4;\n          }\n        } else {\n          assert((ptr & 3) === 0);\n        }\n        return ptr;\n      }\n      function getNextArg(type) {\n        // NOTE: Explicitly ignoring type safety. Otherwise this fails:\n        //       int x = 4; printf(\"%c\\n\", (char)x);\n        var ret;\n        argIndex = prepVararg(argIndex, type);\n        if (type === 'double') {\n          ret = HEAPF64[((argIndex)>>3)];\n          argIndex += 8;\n        } else if (type == 'i64') {\n          ret = [HEAP32[((argIndex)>>2)],\n                 HEAP32[(((argIndex)+(4))>>2)]];\n          argIndex += 8;\n        } else {\n          assert((argIndex & 3) === 0);\n          type = 'i32'; // varargs are always i32, i64, or double\n          ret = HEAP32[((argIndex)>>2)];\n          argIndex += 4;\n        }\n        return ret;\n      }\n  \n      var ret = [];\n      var curr, next, currArg;\n      while (1) {\n        var startTextIndex = textIndex;\n        curr = HEAP8[((textIndex)>>0)];\n        if (curr === 0) break;\n        next = HEAP8[((textIndex+1)>>0)];\n        if (curr == 37) {\n          // Handle flags.\n          var flagAlwaysSigned = false;\n          var flagLeftAlign = false;\n          var flagAlternative = false;\n          var flagZeroPad = false;\n          var flagPadSign = false;\n          flagsLoop: while (1) {\n            switch (next) {\n              case 43:\n                flagAlwaysSigned = true;\n                break;\n              case 45:\n                flagLeftAlign = true;\n                break;\n              case 35:\n                flagAlternative = true;\n                break;\n              case 48:\n                if (flagZeroPad) {\n                  break flagsLoop;\n                } else {\n                  flagZeroPad = true;\n                  break;\n                }\n              case 32:\n                flagPadSign = true;\n                break;\n              default:\n                break flagsLoop;\n            }\n            textIndex++;\n            next = HEAP8[((textIndex+1)>>0)];\n          }\n  \n          // Handle width.\n          var width = 0;\n          if (next == 42) {\n            width = getNextArg('i32');\n            textIndex++;\n            next = HEAP8[((textIndex+1)>>0)];\n          } else {\n            while (next >= 48 && next <= 57) {\n              width = width * 10 + (next - 48);\n              textIndex++;\n              next = HEAP8[((textIndex+1)>>0)];\n            }\n          }\n  \n          // Handle precision.\n          var precisionSet = false, precision = -1;\n          if (next == 46) {\n            precision = 0;\n            precisionSet = true;\n            textIndex++;\n            next = HEAP8[((textIndex+1)>>0)];\n            if (next == 42) {\n              precision = getNextArg('i32');\n              textIndex++;\n            } else {\n              while (1) {\n                var precisionChr = HEAP8[((textIndex+1)>>0)];\n                if (precisionChr < 48 ||\n                    precisionChr > 57) break;\n                precision = precision * 10 + (precisionChr - 48);\n                textIndex++;\n              }\n            }\n            next = HEAP8[((textIndex+1)>>0)];\n          }\n          if (precision < 0) {\n            precision = 6; // Standard default.\n            precisionSet = false;\n          }\n  \n          // Handle integer sizes. WARNING: These assume a 32-bit architecture!\n          var argSize;\n          switch (String.fromCharCode(next)) {\n            case 'h':\n              var nextNext = HEAP8[((textIndex+2)>>0)];\n              if (nextNext == 104) {\n                textIndex++;\n                argSize = 1; // char (actually i32 in varargs)\n              } else {\n                argSize = 2; // short (actually i32 in varargs)\n              }\n              break;\n            case 'l':\n              var nextNext = HEAP8[((textIndex+2)>>0)];\n              if (nextNext == 108) {\n                textIndex++;\n                argSize = 8; // long long\n              } else {\n                argSize = 4; // long\n              }\n              break;\n            case 'L': // long long\n            case 'q': // int64_t\n            case 'j': // intmax_t\n              argSize = 8;\n              break;\n            case 'z': // size_t\n            case 't': // ptrdiff_t\n            case 'I': // signed ptrdiff_t or unsigned size_t\n              argSize = 4;\n              break;\n            default:\n              argSize = null;\n          }\n          if (argSize) textIndex++;\n          next = HEAP8[((textIndex+1)>>0)];\n  \n          // Handle type specifier.\n          switch (String.fromCharCode(next)) {\n            case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': {\n              // Integer.\n              var signed = next == 100 || next == 105;\n              argSize = argSize || 4;\n              currArg = getNextArg('i' + (argSize * 8));\n              var argText;\n              // Flatten i64-1 [low, high] into a (slightly rounded) double\n              if (argSize == 8) {\n                currArg = next == 117 ? convertU32PairToI53(currArg[0], currArg[1]) : convertI32PairToI53(currArg[0], currArg[1]);\n              }\n              // Truncate to requested size.\n              if (argSize <= 4) {\n                var limit = Math.pow(256, argSize) - 1;\n                currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8);\n              }\n              // Format the number.\n              var currAbsArg = Math.abs(currArg);\n              var prefix = '';\n              if (next == 100 || next == 105) {\n                argText = reSign(currArg, 8 * argSize).toString(10);\n              } else if (next == 117) {\n                argText = unSign(currArg, 8 * argSize).toString(10);\n                currArg = Math.abs(currArg);\n              } else if (next == 111) {\n                argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8);\n              } else if (next == 120 || next == 88) {\n                prefix = (flagAlternative && currArg != 0) ? '0x' : '';\n                if (currArg < 0) {\n                  // Represent negative numbers in hex as 2's complement.\n                  currArg = -currArg;\n                  argText = (currAbsArg - 1).toString(16);\n                  var buffer = [];\n                  for (var i = 0; i < argText.length; i++) {\n                    buffer.push((0xF - parseInt(argText[i], 16)).toString(16));\n                  }\n                  argText = buffer.join('');\n                  while (argText.length < argSize * 2) argText = 'f' + argText;\n                } else {\n                  argText = currAbsArg.toString(16);\n                }\n                if (next == 88) {\n                  prefix = prefix.toUpperCase();\n                  argText = argText.toUpperCase();\n                }\n              } else if (next == 112) {\n                if (currAbsArg === 0) {\n                  argText = '(nil)';\n                } else {\n                  prefix = '0x';\n                  argText = currAbsArg.toString(16);\n                }\n              }\n              if (precisionSet) {\n                while (argText.length < precision) {\n                  argText = '0' + argText;\n                }\n              }\n  \n              // Add sign if needed\n              if (currArg >= 0) {\n                if (flagAlwaysSigned) {\n                  prefix = '+' + prefix;\n                } else if (flagPadSign) {\n                  prefix = ' ' + prefix;\n                }\n              }\n  \n              // Move sign to prefix so we zero-pad after the sign\n              if (argText.charAt(0) == '-') {\n                prefix = '-' + prefix;\n                argText = argText.substr(1);\n              }\n  \n              // Add padding.\n              while (prefix.length + argText.length < width) {\n                if (flagLeftAlign) {\n                  argText += ' ';\n                } else {\n                  if (flagZeroPad) {\n                    argText = '0' + argText;\n                  } else {\n                    prefix = ' ' + prefix;\n                  }\n                }\n              }\n  \n              // Insert the result into the buffer.\n              argText = prefix + argText;\n              argText.split('').forEach(function(chr) {\n                ret.push(chr.charCodeAt(0));\n              });\n              break;\n            }\n            case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': {\n              // Float.\n              currArg = getNextArg('double');\n              var argText;\n              if (isNaN(currArg)) {\n                argText = 'nan';\n                flagZeroPad = false;\n              } else if (!isFinite(currArg)) {\n                argText = (currArg < 0 ? '-' : '') + 'inf';\n                flagZeroPad = false;\n              } else {\n                var isGeneral = false;\n                var effectivePrecision = Math.min(precision, 20);\n  \n                // Convert g/G to f/F or e/E, as per:\n                // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html\n                if (next == 103 || next == 71) {\n                  isGeneral = true;\n                  precision = precision || 1;\n                  var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10);\n                  if (precision > exponent && exponent >= -4) {\n                    next = ((next == 103) ? 'f' : 'F').charCodeAt(0);\n                    precision -= exponent + 1;\n                  } else {\n                    next = ((next == 103) ? 'e' : 'E').charCodeAt(0);\n                    precision--;\n                  }\n                  effectivePrecision = Math.min(precision, 20);\n                }\n  \n                if (next == 101 || next == 69) {\n                  argText = currArg.toExponential(effectivePrecision);\n                  // Make sure the exponent has at least 2 digits.\n                  if (/[eE][-+]\\d$/.test(argText)) {\n                    argText = argText.slice(0, -1) + '0' + argText.slice(-1);\n                  }\n                } else if (next == 102 || next == 70) {\n                  argText = currArg.toFixed(effectivePrecision);\n                  if (currArg === 0 && reallyNegative(currArg)) {\n                    argText = '-' + argText;\n                  }\n                }\n  \n                var parts = argText.split('e');\n                if (isGeneral && !flagAlternative) {\n                  // Discard trailing zeros and periods.\n                  while (parts[0].length > 1 && parts[0].includes('.') &&\n                         (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) {\n                    parts[0] = parts[0].slice(0, -1);\n                  }\n                } else {\n                  // Make sure we have a period in alternative mode.\n                  if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.';\n                  // Zero pad until required precision.\n                  while (precision > effectivePrecision++) parts[0] += '0';\n                }\n                argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : '');\n  \n                // Capitalize 'E' if needed.\n                if (next == 69) argText = argText.toUpperCase();\n  \n                // Add sign.\n                if (currArg >= 0) {\n                  if (flagAlwaysSigned) {\n                    argText = '+' + argText;\n                  } else if (flagPadSign) {\n                    argText = ' ' + argText;\n                  }\n                }\n              }\n  \n              // Add padding.\n              while (argText.length < width) {\n                if (flagLeftAlign) {\n                  argText += ' ';\n                } else {\n                  if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) {\n                    argText = argText[0] + '0' + argText.slice(1);\n                  } else {\n                    argText = (flagZeroPad ? '0' : ' ') + argText;\n                  }\n                }\n              }\n  \n              // Adjust case.\n              if (next < 97) argText = argText.toUpperCase();\n  \n              // Insert the result into the buffer.\n              argText.split('').forEach(function(chr) {\n                ret.push(chr.charCodeAt(0));\n              });\n              break;\n            }\n            case 's': {\n              // String.\n              var arg = getNextArg('i8*');\n              var argLength = arg ? strLen(arg) : '(null)'.length;\n              if (precisionSet) argLength = Math.min(argLength, precision);\n              if (!flagLeftAlign) {\n                while (argLength < width--) {\n                  ret.push(32);\n                }\n              }\n              if (arg) {\n                for (var i = 0; i < argLength; i++) {\n                  ret.push(HEAPU8[((arg++)>>0)]);\n                }\n              } else {\n                ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true));\n              }\n              if (flagLeftAlign) {\n                while (argLength < width--) {\n                  ret.push(32);\n                }\n              }\n              break;\n            }\n            case 'c': {\n              // Character.\n              if (flagLeftAlign) ret.push(getNextArg('i8'));\n              while (--width > 0) {\n                ret.push(32);\n              }\n              if (!flagLeftAlign) ret.push(getNextArg('i8'));\n              break;\n            }\n            case 'n': {\n              // Write the length written so far to the next parameter.\n              var ptr = getNextArg('i32*');\n              HEAP32[((ptr)>>2)] = ret.length;\n              break;\n            }\n            case '%': {\n              // Literal percent sign.\n              ret.push(curr);\n              break;\n            }\n            default: {\n              // Unknown specifiers remain untouched.\n              for (var i = startTextIndex; i < textIndex + 2; i++) {\n                ret.push(HEAP8[((i)>>0)]);\n              }\n            }\n          }\n          textIndex += 2;\n          // TODO: Support a/A (hex float) and m (last error) specifiers.\n          // TODO: Support %1${specifier} for arg selection.\n        } else {\n          ret.push(curr);\n          textIndex += 1;\n        }\n      }\n      return ret;\n    }\n  \n  function traverseStack(args) {\n      if (!args || !args.callee || !args.callee.name) {\n        return [null, '', ''];\n      }\n  \n      var funstr = args.callee.toString();\n      var funcname = args.callee.name;\n      var str = '(';\n      var first = true;\n      for (var i in args) {\n        var a = args[i];\n        if (!first) {\n          str += \", \";\n        }\n        first = false;\n        if (typeof a == 'number' || typeof a == 'string') {\n          str += a;\n        } else {\n          str += '(' + typeof a + ')';\n        }\n      }\n      str += ')';\n      var caller = args.callee.caller;\n      args = caller ? caller.arguments : [];\n      if (first)\n        str = '';\n      return [args, funcname, str];\n    }\n  \n  function jsStackTrace() {\n      var error = new Error();\n      if (!error.stack) {\n        // IE10+ special cases: It does have callstack info, but it is only\n        // populated if an Error object is thrown, so try that as a special-case.\n        try {\n          throw new Error();\n        } catch(e) {\n          error = e;\n        }\n        if (!error.stack) {\n          return '(no stack trace available)';\n        }\n      }\n      return error.stack.toString();\n    }\n  \n  /** @param {number=} flags */\n  function _emscripten_get_callstack_js(flags) {\n      var callstack = jsStackTrace();\n  \n      // Find the symbols in the callstack that corresponds to the functions that\n      // report callstack information, and remove everything up to these from the\n      // output.\n      var iThisFunc = callstack.lastIndexOf('_emscripten_log');\n      var iThisFunc2 = callstack.lastIndexOf('_emscripten_get_callstack');\n      var iNextLine = callstack.indexOf('\\n', Math.max(iThisFunc, iThisFunc2))+1;\n      callstack = callstack.slice(iNextLine);\n  \n      if (flags & 32) {\n        warnOnce('EM_LOG_DEMANGLE is deprecated; ignoring');\n      }\n  \n      // If user requested to see the original source stack, but no source map\n      // information is available, just fall back to showing the JS stack.\n      if (flags & 8 && typeof emscripten_source_map == 'undefined') {\n        warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with \"--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js\" linker flag to add source map loading to code.');\n        flags ^= 8;\n        flags |= 16;\n      }\n  \n      var stack_args = null;\n      if (flags & 128) {\n        // To get the actual parameters to the functions, traverse the stack via\n        // the unfortunately deprecated 'arguments.callee' method, if it works:\n        stack_args = traverseStack(arguments);\n        while (stack_args[1].includes('_emscripten_'))\n          stack_args = traverseStack(stack_args[0]);\n      }\n  \n      // Process all lines:\n      var lines = callstack.split('\\n');\n      callstack = '';\n      // New FF30 with column info: extract components of form:\n      // '       Object._main@http://server.com:4324:12'\n      var newFirefoxRe = new RegExp('\\\\s*(.*?)@(.*?):([0-9]+):([0-9]+)');\n      // Old FF without column info: extract components of form:\n      // '       Object._main@http://server.com:4324'\n      var firefoxRe = new RegExp('\\\\s*(.*?)@(.*):(.*)(:(.*))?');\n      // Extract components of form:\n      // '    at Object._main (http://server.com/file.html:4324:12)'\n      var chromeRe = new RegExp('\\\\s*at (.*?) \\\\\\((.*):(.*):(.*)\\\\\\)');\n  \n      for (var l in lines) {\n        var line = lines[l];\n  \n        var symbolName = '';\n        var file = '';\n        var lineno = 0;\n        var column = 0;\n  \n        var parts = chromeRe.exec(line);\n        if (parts && parts.length == 5) {\n          symbolName = parts[1];\n          file = parts[2];\n          lineno = parts[3];\n          column = parts[4];\n        } else {\n          parts = newFirefoxRe.exec(line);\n          if (!parts) parts = firefoxRe.exec(line);\n          if (parts && parts.length >= 4) {\n            symbolName = parts[1];\n            file = parts[2];\n            lineno = parts[3];\n            // Old Firefox doesn't carry column information, but in new FF30, it\n            // is present. See https://bugzilla.mozilla.org/show_bug.cgi?id=762556\n            column = parts[4]|0;\n          } else {\n            // Was not able to extract this line for demangling/sourcemapping\n            // purposes. Output it as-is.\n            callstack += line + '\\n';\n            continue;\n          }\n        }\n  \n        var haveSourceMap = false;\n  \n        if (flags & 8) {\n          var orig = emscripten_source_map.originalPositionFor({line: lineno, column: column});\n          haveSourceMap = (orig && orig.source);\n          if (haveSourceMap) {\n            if (flags & 64) {\n              orig.source = orig.source.substring(orig.source.replace(/\\\\/g, \"/\").lastIndexOf('/')+1);\n            }\n            callstack += '    at ' + symbolName + ' (' + orig.source + ':' + orig.line + ':' + orig.column + ')\\n';\n          }\n        }\n        if ((flags & 16) || !haveSourceMap) {\n          if (flags & 64) {\n            file = file.substring(file.replace(/\\\\/g, \"/\").lastIndexOf('/')+1);\n          }\n          callstack += (haveSourceMap ? ('     = ' + symbolName) : ('    at '+ symbolName)) + ' (' + file + ':' + lineno + ':' + column + ')\\n';\n        }\n  \n        // If we are still keeping track with the callstack by traversing via\n        // 'arguments.callee', print the function parameters as well.\n        if (flags & 128 && stack_args[0]) {\n          if (stack_args[1] == symbolName && stack_args[2].length > 0) {\n            callstack = callstack.replace(/\\s+$/, '');\n            callstack += ' with values: ' + stack_args[1] + stack_args[2] + '\\n';\n          }\n          stack_args = traverseStack(stack_args[0]);\n        }\n      }\n      // Trim extra whitespace at the end of the output.\n      callstack = callstack.replace(/\\s+$/, '');\n      return callstack;\n    }\n  function _emscripten_log_js(flags, str) {\n      if (flags & 24) {\n        str = str.replace(/\\s+$/, ''); // Ensure the message and the callstack are joined cleanly with exactly one newline.\n        str += (str.length > 0 ? '\\n' : '') + _emscripten_get_callstack_js(flags);\n      }\n  \n      if (flags & 1) {\n        if (flags & 4) {\n          console.error(str);\n        } else if (flags & 2) {\n          console.warn(str);\n        } else if (flags & 512) {\n          console.info(str);\n        } else if (flags & 256) {\n          console.debug(str);\n        } else {\n          console.log(str);\n        }\n      } else if (flags & 6) {\n        err(str);\n      } else {\n        out(str);\n      }\n    }\n  function _emscripten_log(flags, format, varargs) {\n      var result = formatString(format, varargs);\n      var str = UTF8ArrayToString(result, 0);\n      _emscripten_log_js(flags, str);\n    }\n\n  function _emscripten_memcpy_big(dest, src, num) {\n      HEAPU8.copyWithin(dest, src, src + num);\n    }\n\n  function getHeapMax() {\n      return HEAPU8.length;\n    }\n  \n  function abortOnCannotGrowMemory(requestedSize) {\n      abort('Cannot enlarge memory arrays to size ' + requestedSize + ' bytes (OOM). Either (1) compile with -sINITIAL_MEMORY=X with X higher than the current value ' + HEAP8.length + ', (2) compile with -sALLOW_MEMORY_GROWTH which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -sABORTING_MALLOC=0');\n    }\n  function _emscripten_resize_heap(requestedSize) {\n      var oldSize = HEAPU8.length;\n      requestedSize = requestedSize >>> 0;\n      abortOnCannotGrowMemory(requestedSize);\n    }\n\n  var ENV = {};\n  \n  function getExecutableName() {\n      return thisProgram || './this.program';\n    }\n  function getEnvStrings() {\n      if (!getEnvStrings.strings) {\n        // Default values.\n        // Browser language detection #8751\n        var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8';\n        var env = {\n          'USER': 'web_user',\n          'LOGNAME': 'web_user',\n          'PATH': '/',\n          'PWD': '/',\n          'HOME': '/home/web_user',\n          'LANG': lang,\n          '_': getExecutableName()\n        };\n        // Apply the user-provided values, if any.\n        for (var x in ENV) {\n          // x is a key in ENV; if ENV[x] is undefined, that means it was\n          // explicitly set to be so. We allow user code to do that to\n          // force variables with default values to remain unset.\n          if (ENV[x] === undefined) delete env[x];\n          else env[x] = ENV[x];\n        }\n        var strings = [];\n        for (var x in env) {\n          strings.push(x + '=' + env[x]);\n        }\n        getEnvStrings.strings = strings;\n      }\n      return getEnvStrings.strings;\n    }\n  \n  /** @param {boolean=} dontAddNull */\n  function writeAsciiToMemory(str, buffer, dontAddNull) {\n      for (var i = 0; i < str.length; ++i) {\n        assert(str.charCodeAt(i) === (str.charCodeAt(i) & 0xff));\n        HEAP8[((buffer++)>>0)] = str.charCodeAt(i);\n      }\n      // Null-terminate the pointer to the HEAP.\n      if (!dontAddNull) HEAP8[((buffer)>>0)] = 0;\n    }\n  \n  var SYSCALLS = {varargs:undefined,get:function() {\n        assert(SYSCALLS.varargs != undefined);\n        SYSCALLS.varargs += 4;\n        var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];\n        return ret;\n      },getStr:function(ptr) {\n        var ret = UTF8ToString(ptr);\n        return ret;\n      }};\n  function _environ_get(__environ, environ_buf) {\n      var bufSize = 0;\n      getEnvStrings().forEach(function(string, i) {\n        var ptr = environ_buf + bufSize;\n        HEAPU32[(((__environ)+(i*4))>>2)] = ptr;\n        writeAsciiToMemory(string, ptr);\n        bufSize += string.length + 1;\n      });\n      return 0;\n    }\n\n  \n  function _environ_sizes_get(penviron_count, penviron_buf_size) {\n      var strings = getEnvStrings();\n      HEAPU32[((penviron_count)>>2)] = strings.length;\n      var bufSize = 0;\n      strings.forEach(function(string) {\n        bufSize += string.length + 1;\n      });\n      HEAPU32[((penviron_buf_size)>>2)] = bufSize;\n      return 0;\n    }\n\n  function _fd_close(fd) {\n      abort('fd_close called without SYSCALLS_REQUIRE_FILESYSTEM');\n    }\n\n  function convertI32PairToI53Checked(lo, hi) {\n      assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32\n      assert(hi === (hi|0));                    // hi should be a i32\n      return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;\n    }\n  \n  \n  \n  \n  function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {\n      return 70;\n    }\n\n  var printCharBuffers = [null,[],[]];\n  function printChar(stream, curr) {\n      var buffer = printCharBuffers[stream];\n      assert(buffer);\n      if (curr === 0 || curr === 10) {\n        (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0));\n        buffer.length = 0;\n      } else {\n        buffer.push(curr);\n      }\n    }\n  \n  function flush_NO_FILESYSTEM() {\n      // flush anything remaining in the buffers during shutdown\n      _fflush(0);\n      if (printCharBuffers[1].length) printChar(1, 10);\n      if (printCharBuffers[2].length) printChar(2, 10);\n    }\n  \n  \n  function _fd_write(fd, iov, iovcnt, pnum) {\n      // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0\n      var num = 0;\n      for (var i = 0; i < iovcnt; i++) {\n        var ptr = HEAPU32[((iov)>>2)];\n        var len = HEAPU32[(((iov)+(4))>>2)];\n        iov += 8;\n        for (var j = 0; j < len; j++) {\n          printChar(fd, HEAPU8[ptr+j]);\n        }\n        num += len;\n      }\n      HEAPU32[((pnum)>>2)] = num;\n      return 0;\n    }\n\n  function __isLeapYear(year) {\n        return year%4 === 0 && (year%100 !== 0 || year%400 === 0);\n    }\n  \n  function __arraySum(array, index) {\n      var sum = 0;\n      for (var i = 0; i <= index; sum += array[i++]) {\n        // no-op\n      }\n      return sum;\n    }\n  \n  \n  var __MONTH_DAYS_LEAP = [31,29,31,30,31,30,31,31,30,31,30,31];\n  \n  var __MONTH_DAYS_REGULAR = [31,28,31,30,31,30,31,31,30,31,30,31];\n  function __addDays(date, days) {\n      var newDate = new Date(date.getTime());\n      while (days > 0) {\n        var leap = __isLeapYear(newDate.getFullYear());\n        var currentMonth = newDate.getMonth();\n        var daysInCurrentMonth = (leap ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[currentMonth];\n  \n        if (days > daysInCurrentMonth-newDate.getDate()) {\n          // we spill over to next month\n          days -= (daysInCurrentMonth-newDate.getDate()+1);\n          newDate.setDate(1);\n          if (currentMonth < 11) {\n            newDate.setMonth(currentMonth+1)\n          } else {\n            newDate.setMonth(0);\n            newDate.setFullYear(newDate.getFullYear()+1);\n          }\n        } else {\n          // we stay in current month\n          newDate.setDate(newDate.getDate()+days);\n          return newDate;\n        }\n      }\n  \n      return newDate;\n    }\n  \n  \n  \n  \n  function writeArrayToMemory(array, buffer) {\n      assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)')\n      HEAP8.set(array, buffer);\n    }\n  function _strftime(s, maxsize, format, tm) {\n      // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr);\n      // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html\n  \n      var tm_zone = HEAP32[(((tm)+(40))>>2)];\n  \n      var date = {\n        tm_sec: HEAP32[((tm)>>2)],\n        tm_min: HEAP32[(((tm)+(4))>>2)],\n        tm_hour: HEAP32[(((tm)+(8))>>2)],\n        tm_mday: HEAP32[(((tm)+(12))>>2)],\n        tm_mon: HEAP32[(((tm)+(16))>>2)],\n        tm_year: HEAP32[(((tm)+(20))>>2)],\n        tm_wday: HEAP32[(((tm)+(24))>>2)],\n        tm_yday: HEAP32[(((tm)+(28))>>2)],\n        tm_isdst: HEAP32[(((tm)+(32))>>2)],\n        tm_gmtoff: HEAP32[(((tm)+(36))>>2)],\n        tm_zone: tm_zone ? UTF8ToString(tm_zone) : ''\n      };\n  \n      var pattern = UTF8ToString(format);\n  \n      // expand format\n      var EXPANSION_RULES_1 = {\n        '%c': '%a %b %d %H:%M:%S %Y',     // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug  3 14:02:01 2013\n        '%D': '%m/%d/%y',                 // Equivalent to %m / %d / %y\n        '%F': '%Y-%m-%d',                 // Equivalent to %Y - %m - %d\n        '%h': '%b',                       // Equivalent to %b\n        '%r': '%I:%M:%S %p',              // Replaced by the time in a.m. and p.m. notation\n        '%R': '%H:%M',                    // Replaced by the time in 24-hour notation\n        '%T': '%H:%M:%S',                 // Replaced by the time\n        '%x': '%m/%d/%y',                 // Replaced by the locale's appropriate date representation\n        '%X': '%H:%M:%S',                 // Replaced by the locale's appropriate time representation\n        // Modified Conversion Specifiers\n        '%Ec': '%c',                      // Replaced by the locale's alternative appropriate date and time representation.\n        '%EC': '%C',                      // Replaced by the name of the base year (period) in the locale's alternative representation.\n        '%Ex': '%m/%d/%y',                // Replaced by the locale's alternative date representation.\n        '%EX': '%H:%M:%S',                // Replaced by the locale's alternative time representation.\n        '%Ey': '%y',                      // Replaced by the offset from %EC (year only) in the locale's alternative representation.\n        '%EY': '%Y',                      // Replaced by the full alternative year representation.\n        '%Od': '%d',                      // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading zeros if there is any alternative symbol for zero; otherwise, with leading <space> characters.\n        '%Oe': '%e',                      // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading <space> characters.\n        '%OH': '%H',                      // Replaced by the hour (24-hour clock) using the locale's alternative numeric symbols.\n        '%OI': '%I',                      // Replaced by the hour (12-hour clock) using the locale's alternative numeric symbols.\n        '%Om': '%m',                      // Replaced by the month using the locale's alternative numeric symbols.\n        '%OM': '%M',                      // Replaced by the minutes using the locale's alternative numeric symbols.\n        '%OS': '%S',                      // Replaced by the seconds using the locale's alternative numeric symbols.\n        '%Ou': '%u',                      // Replaced by the weekday as a number in the locale's alternative representation (Monday=1).\n        '%OU': '%U',                      // Replaced by the week number of the year (Sunday as the first day of the week, rules corresponding to %U ) using the locale's alternative numeric symbols.\n        '%OV': '%V',                      // Replaced by the week number of the year (Monday as the first day of the week, rules corresponding to %V ) using the locale's alternative numeric symbols.\n        '%Ow': '%w',                      // Replaced by the number of the weekday (Sunday=0) using the locale's alternative numeric symbols.\n        '%OW': '%W',                      // Replaced by the week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols.\n        '%Oy': '%y',                      // Replaced by the year (offset from %C ) using the locale's alternative numeric symbols.\n      };\n      for (var rule in EXPANSION_RULES_1) {\n        pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]);\n      }\n  \n      var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n      var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\n  \n      function leadingSomething(value, digits, character) {\n        var str = typeof value == 'number' ? value.toString() : (value || '');\n        while (str.length < digits) {\n          str = character[0]+str;\n        }\n        return str;\n      }\n  \n      function leadingNulls(value, digits) {\n        return leadingSomething(value, digits, '0');\n      }\n  \n      function compareByDay(date1, date2) {\n        function sgn(value) {\n          return value < 0 ? -1 : (value > 0 ? 1 : 0);\n        }\n  \n        var compare;\n        if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) {\n          if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) {\n            compare = sgn(date1.getDate()-date2.getDate());\n          }\n        }\n        return compare;\n      }\n  \n      function getFirstWeekStartDate(janFourth) {\n          switch (janFourth.getDay()) {\n            case 0: // Sunday\n              return new Date(janFourth.getFullYear()-1, 11, 29);\n            case 1: // Monday\n              return janFourth;\n            case 2: // Tuesday\n              return new Date(janFourth.getFullYear(), 0, 3);\n            case 3: // Wednesday\n              return new Date(janFourth.getFullYear(), 0, 2);\n            case 4: // Thursday\n              return new Date(janFourth.getFullYear(), 0, 1);\n            case 5: // Friday\n              return new Date(janFourth.getFullYear()-1, 11, 31);\n            case 6: // Saturday\n              return new Date(janFourth.getFullYear()-1, 11, 30);\n          }\n      }\n  \n      function getWeekBasedYear(date) {\n          var thisDate = __addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday);\n  \n          var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);\n          var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4);\n  \n          var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);\n          var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);\n  \n          if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {\n            // this date is after the start of the first week of this year\n            if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {\n              return thisDate.getFullYear()+1;\n            }\n            return thisDate.getFullYear();\n          }\n          return thisDate.getFullYear()-1;\n      }\n  \n      var EXPANSION_RULES_2 = {\n        '%a': function(date) {\n          return WEEKDAYS[date.tm_wday].substring(0,3);\n        },\n        '%A': function(date) {\n          return WEEKDAYS[date.tm_wday];\n        },\n        '%b': function(date) {\n          return MONTHS[date.tm_mon].substring(0,3);\n        },\n        '%B': function(date) {\n          return MONTHS[date.tm_mon];\n        },\n        '%C': function(date) {\n          var year = date.tm_year+1900;\n          return leadingNulls((year/100)|0,2);\n        },\n        '%d': function(date) {\n          return leadingNulls(date.tm_mday, 2);\n        },\n        '%e': function(date) {\n          return leadingSomething(date.tm_mday, 2, ' ');\n        },\n        '%g': function(date) {\n          // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year.\n          // In this system, weeks begin on a Monday and week 1 of the year is the week that includes\n          // January 4th, which is also the week that includes the first Thursday of the year, and\n          // is also the first week that contains at least four days in the year.\n          // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of\n          // the last week of the preceding year; thus, for Saturday 2nd January 1999,\n          // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th,\n          // or 31st is a Monday, it and any following days are part of week 1 of the following year.\n          // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01.\n  \n          return getWeekBasedYear(date).toString().substring(2);\n        },\n        '%G': function(date) {\n          return getWeekBasedYear(date);\n        },\n        '%H': function(date) {\n          return leadingNulls(date.tm_hour, 2);\n        },\n        '%I': function(date) {\n          var twelveHour = date.tm_hour;\n          if (twelveHour == 0) twelveHour = 12;\n          else if (twelveHour > 12) twelveHour -= 12;\n          return leadingNulls(twelveHour, 2);\n        },\n        '%j': function(date) {\n          // Day of the year (001-366)\n          return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, date.tm_mon-1), 3);\n        },\n        '%m': function(date) {\n          return leadingNulls(date.tm_mon+1, 2);\n        },\n        '%M': function(date) {\n          return leadingNulls(date.tm_min, 2);\n        },\n        '%n': function() {\n          return '\\n';\n        },\n        '%p': function(date) {\n          if (date.tm_hour >= 0 && date.tm_hour < 12) {\n            return 'AM';\n          }\n          return 'PM';\n        },\n        '%S': function(date) {\n          return leadingNulls(date.tm_sec, 2);\n        },\n        '%t': function() {\n          return '\\t';\n        },\n        '%u': function(date) {\n          return date.tm_wday || 7;\n        },\n        '%U': function(date) {\n          var days = date.tm_yday + 7 - date.tm_wday;\n          return leadingNulls(Math.floor(days / 7), 2);\n        },\n        '%V': function(date) {\n          // Replaced by the week number of the year (Monday as the first day of the week)\n          // as a decimal number [01,53]. If the week containing 1 January has four\n          // or more days in the new year, then it is considered week 1.\n          // Otherwise, it is the last week of the previous year, and the next week is week 1.\n          // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday]\n          var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7 ) / 7);\n          // If 1 Jan is just 1-3 days past Monday, the previous week\n          // is also in this year.\n          if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) {\n            val++;\n          }\n          if (!val) {\n            val = 52;\n            // If 31 December of prev year a Thursday, or Friday of a\n            // leap year, then the prev year has 53 weeks.\n            var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7;\n            if (dec31 == 4 || (dec31 == 5 && __isLeapYear(date.tm_year%400-1))) {\n              val++;\n            }\n          } else if (val == 53) {\n            // If 1 January is not a Thursday, and not a Wednesday of a\n            // leap year, then this year has only 52 weeks.\n            var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7;\n            if (jan1 != 4 && (jan1 != 3 || !__isLeapYear(date.tm_year)))\n              val = 1;\n          }\n          return leadingNulls(val, 2);\n        },\n        '%w': function(date) {\n          return date.tm_wday;\n        },\n        '%W': function(date) {\n          var days = date.tm_yday + 7 - ((date.tm_wday + 6) % 7);\n          return leadingNulls(Math.floor(days / 7), 2);\n        },\n        '%y': function(date) {\n          // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year]\n          return (date.tm_year+1900).toString().substring(2);\n        },\n        '%Y': function(date) {\n          // Replaced by the year as a decimal number (for example, 1997). [ tm_year]\n          return date.tm_year+1900;\n        },\n        '%z': function(date) {\n          // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ).\n          // For example, \"-0430\" means 4 hours 30 minutes behind UTC (west of Greenwich).\n          var off = date.tm_gmtoff;\n          var ahead = off >= 0;\n          off = Math.abs(off) / 60;\n          // convert from minutes into hhmm format (which means 60 minutes = 100 units)\n          off = (off / 60)*100 + (off % 60);\n          return (ahead ? '+' : '-') + String(\"0000\" + off).slice(-4);\n        },\n        '%Z': function(date) {\n          return date.tm_zone;\n        },\n        '%%': function() {\n          return '%';\n        }\n      };\n  \n      // Replace %% with a pair of NULLs (which cannot occur in a C string), then\n      // re-inject them after processing.\n      pattern = pattern.replace(/%%/g, '\\0\\0')\n      for (var rule in EXPANSION_RULES_2) {\n        if (pattern.includes(rule)) {\n          pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date));\n        }\n      }\n      pattern = pattern.replace(/\\0\\0/g, '%')\n  \n      var bytes = intArrayFromString(pattern, false);\n      if (bytes.length > maxsize) {\n        return 0;\n      }\n  \n      writeArrayToMemory(bytes, s);\n      return bytes.length-1;\n    }\n  function _strftime_l(s, maxsize, format, tm, loc) {\n      return _strftime(s, maxsize, format, tm); // no locale support yet\n    }\n\n  \n  function _proc_exit(code) {\n      EXITSTATUS = code;\n      if (!keepRuntimeAlive()) {\n        if (Module['onExit']) Module['onExit'](code);\n        ABORT = true;\n      }\n      quit_(code, new ExitStatus(code));\n    }\n  /** @param {boolean|number=} implicit */\n  function exitJS(status, implicit) {\n      EXITSTATUS = status;\n  \n      checkUnflushedContent();\n  \n      // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down\n      if (keepRuntimeAlive() && !implicit) {\n        var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)';\n        err(msg);\n      }\n  \n      _proc_exit(status);\n    }\n\n  function handleException(e) {\n      // Certain exception types we do not treat as errors since they are used for\n      // internal control flow.\n      // 1. ExitStatus, which is thrown by exit()\n      // 2. \"unwind\", which is thrown by emscripten_unwind_to_js_event_loop() and others\n      //    that wish to return to JS event loop.\n      if (e instanceof ExitStatus || e == 'unwind') {\n        return EXITSTATUS;\n      }\n      checkStackCookie();\n      if (e instanceof WebAssembly.RuntimeError) {\n        if (_emscripten_stack_get_current() <= 0) {\n          err('Stack overflow detected.  You can try increasing -sSTACK_SIZE (currently set to ' + STACK_SIZE + ')');\n        }\n      }\n      quit_(1, e);\n    }\n\nvar ASSERTIONS = true;\n\nfunction checkIncomingModuleAPI() {\n  ignoredModuleProp('fetchSettings');\n}\nvar asmLibraryArg = {\n  \"__assert_fail\": ___assert_fail,\n  \"__cxa_begin_catch\": ___cxa_begin_catch,\n  \"__cxa_end_catch\": ___cxa_end_catch,\n  \"__cxa_find_matching_catch_2\": ___cxa_find_matching_catch_2,\n  \"__cxa_find_matching_catch_3\": ___cxa_find_matching_catch_3,\n  \"__cxa_throw\": ___cxa_throw,\n  \"__resumeException\": ___resumeException,\n  \"abort\": _abort,\n  \"emscripten_asm_const_int\": _emscripten_asm_const_int,\n  \"emscripten_log\": _emscripten_log,\n  \"emscripten_memcpy_big\": _emscripten_memcpy_big,\n  \"emscripten_resize_heap\": _emscripten_resize_heap,\n  \"environ_get\": _environ_get,\n  \"environ_sizes_get\": _environ_sizes_get,\n  \"fd_close\": _fd_close,\n  \"fd_seek\": _fd_seek,\n  \"fd_write\": _fd_write,\n  \"invoke_i\": invoke_i,\n  \"invoke_idiii\": invoke_idiii,\n  \"invoke_ii\": invoke_ii,\n  \"invoke_iii\": invoke_iii,\n  \"invoke_iiii\": invoke_iiii,\n  \"invoke_iiiii\": invoke_iiiii,\n  \"invoke_iiiiii\": invoke_iiiiii,\n  \"invoke_iiiiiii\": invoke_iiiiiii,\n  \"invoke_iij\": invoke_iij,\n  \"invoke_iiji\": invoke_iiji,\n  \"invoke_iijiii\": invoke_iijiii,\n  \"invoke_iijj\": invoke_iijj,\n  \"invoke_iijjiii\": invoke_iijjiii,\n  \"invoke_ijjiii\": invoke_ijjiii,\n  \"invoke_j\": invoke_j,\n  \"invoke_v\": invoke_v,\n  \"invoke_vdiii\": invoke_vdiii,\n  \"invoke_vi\": invoke_vi,\n  \"invoke_vii\": invoke_vii,\n  \"invoke_viii\": invoke_viii,\n  \"invoke_viiii\": invoke_viiii,\n  \"invoke_vij\": invoke_vij,\n  \"invoke_vijj\": invoke_vijj,\n  \"invoke_vjjiii\": invoke_vjjiii,\n  \"strftime_l\": _strftime_l\n};\nvar asm = createWasm();\n/** @type {function(...*):?} */\nvar ___wasm_call_ctors = Module[\"___wasm_call_ctors\"] = createExportWrapper(\"__wasm_call_ctors\");\n\n/** @type {function(...*):?} */\nvar _main = Module[\"_main\"] = createExportWrapper(\"main\");\n\n/** @type {function(...*):?} */\nvar _on_init_callback = Module[\"_on_init_callback\"] = createExportWrapper(\"on_init_callback\");\n\n/** @type {function(...*):?} */\nvar _on_screen_shared = Module[\"_on_screen_shared\"] = createExportWrapper(\"on_screen_shared\");\n\n/** @type {function(...*):?} */\nvar _on_join_room_callback = Module[\"_on_join_room_callback\"] = createExportWrapper(\"on_join_room_callback\");\n\n/** @type {function(...*):?} */\nvar ___cxa_free_exception = Module[\"___cxa_free_exception\"] = createExportWrapper(\"__cxa_free_exception\");\n\n/** @type {function(...*):?} */\nvar ___errno_location = Module[\"___errno_location\"] = createExportWrapper(\"__errno_location\");\n\n/** @type {function(...*):?} */\nvar _fflush = Module[\"_fflush\"] = createExportWrapper(\"fflush\");\n\n/** @type {function(...*):?} */\nvar _malloc = Module[\"_malloc\"] = createExportWrapper(\"malloc\");\n\n/** @type {function(...*):?} */\nvar _free = Module[\"_free\"] = createExportWrapper(\"free\");\n\n/** @type {function(...*):?} */\nvar setTempRet0 = Module[\"setTempRet0\"] = createExportWrapper(\"setTempRet0\");\n\n/** @type {function(...*):?} */\nvar _emscripten_stack_init = Module[\"_emscripten_stack_init\"] = function() {\n  return (_emscripten_stack_init = Module[\"_emscripten_stack_init\"] = Module[\"asm\"][\"emscripten_stack_init\"]).apply(null, arguments);\n};\n\n/** @type {function(...*):?} */\nvar _emscripten_stack_get_free = Module[\"_emscripten_stack_get_free\"] = function() {\n  return (_emscripten_stack_get_free = Module[\"_emscripten_stack_get_free\"] = Module[\"asm\"][\"emscripten_stack_get_free\"]).apply(null, arguments);\n};\n\n/** @type {function(...*):?} */\nvar _emscripten_stack_get_base = Module[\"_emscripten_stack_get_base\"] = function() {\n  return (_emscripten_stack_get_base = Module[\"_emscripten_stack_get_base\"] = Module[\"asm\"][\"emscripten_stack_get_base\"]).apply(null, arguments);\n};\n\n/** @type {function(...*):?} */\nvar _emscripten_stack_get_end = Module[\"_emscripten_stack_get_end\"] = function() {\n  return (_emscripten_stack_get_end = Module[\"_emscripten_stack_get_end\"] = Module[\"asm\"][\"emscripten_stack_get_end\"]).apply(null, arguments);\n};\n\n/** @type {function(...*):?} */\nvar stackSave = Module[\"stackSave\"] = createExportWrapper(\"stackSave\");\n\n/** @type {function(...*):?} */\nvar stackRestore = Module[\"stackRestore\"] = createExportWrapper(\"stackRestore\");\n\n/** @type {function(...*):?} */\nvar stackAlloc = Module[\"stackAlloc\"] = createExportWrapper(\"stackAlloc\");\n\n/** @type {function(...*):?} */\nvar _emscripten_stack_get_current = Module[\"_emscripten_stack_get_current\"] = function() {\n  return (_emscripten_stack_get_current = Module[\"_emscripten_stack_get_current\"] = Module[\"asm\"][\"emscripten_stack_get_current\"]).apply(null, arguments);\n};\n\n/** @type {function(...*):?} */\nvar ___cxa_can_catch = Module[\"___cxa_can_catch\"] = createExportWrapper(\"__cxa_can_catch\");\n\n/** @type {function(...*):?} */\nvar ___cxa_is_pointer_type = Module[\"___cxa_is_pointer_type\"] = createExportWrapper(\"__cxa_is_pointer_type\");\n\n/** @type {function(...*):?} */\nvar dynCall_iij = Module[\"dynCall_iij\"] = createExportWrapper(\"dynCall_iij\");\n\n/** @type {function(...*):?} */\nvar dynCall_iijiii = Module[\"dynCall_iijiii\"] = createExportWrapper(\"dynCall_iijiii\");\n\n/** @type {function(...*):?} */\nvar dynCall_iijjiii = Module[\"dynCall_iijjiii\"] = createExportWrapper(\"dynCall_iijjiii\");\n\n/** @type {function(...*):?} */\nvar dynCall_j = Module[\"dynCall_j\"] = createExportWrapper(\"dynCall_j\");\n\n/** @type {function(...*):?} */\nvar dynCall_iiji = Module[\"dynCall_iiji\"] = createExportWrapper(\"dynCall_iiji\");\n\n/** @type {function(...*):?} */\nvar dynCall_vjjiii = Module[\"dynCall_vjjiii\"] = createExportWrapper(\"dynCall_vjjiii\");\n\n/** @type {function(...*):?} */\nvar dynCall_ijjiii = Module[\"dynCall_ijjiii\"] = createExportWrapper(\"dynCall_ijjiii\");\n\n/** @type {function(...*):?} */\nvar dynCall_vijj = Module[\"dynCall_vijj\"] = createExportWrapper(\"dynCall_vijj\");\n\n/** @type {function(...*):?} */\nvar dynCall_iijj = Module[\"dynCall_iijj\"] = createExportWrapper(\"dynCall_iijj\");\n\n/** @type {function(...*):?} */\nvar dynCall_vij = Module[\"dynCall_vij\"] = createExportWrapper(\"dynCall_vij\");\n\n/** @type {function(...*):?} */\nvar dynCall_jiji = Module[\"dynCall_jiji\"] = createExportWrapper(\"dynCall_jiji\");\n\n/** @type {function(...*):?} */\nvar dynCall_viijii = Module[\"dynCall_viijii\"] = createExportWrapper(\"dynCall_viijii\");\n\n/** @type {function(...*):?} */\nvar dynCall_iiiiij = Module[\"dynCall_iiiiij\"] = createExportWrapper(\"dynCall_iiiiij\");\n\n/** @type {function(...*):?} */\nvar dynCall_iiiiijj = Module[\"dynCall_iiiiijj\"] = createExportWrapper(\"dynCall_iiiiijj\");\n\n/** @type {function(...*):?} */\nvar dynCall_iiiiiijj = Module[\"dynCall_iiiiiijj\"] = createExportWrapper(\"dynCall_iiiiiijj\");\n\n\nfunction invoke_iii(index,a1,a2) {\n  var sp = stackSave();\n  try {\n    return getWasmTableEntry(index)(a1,a2);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_v(index) {\n  var sp = stackSave();\n  try {\n    getWasmTableEntry(index)();\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_i(index) {\n  var sp = stackSave();\n  try {\n    return getWasmTableEntry(index)();\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iiii(index,a1,a2,a3) {\n  var sp = stackSave();\n  try {\n    return getWasmTableEntry(index)(a1,a2,a3);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_vii(index,a1,a2) {\n  var sp = stackSave();\n  try {\n    getWasmTableEntry(index)(a1,a2);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_viii(index,a1,a2,a3) {\n  var sp = stackSave();\n  try {\n    getWasmTableEntry(index)(a1,a2,a3);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_vi(index,a1) {\n  var sp = stackSave();\n  try {\n    getWasmTableEntry(index)(a1);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_viiii(index,a1,a2,a3,a4) {\n  var sp = stackSave();\n  try {\n    getWasmTableEntry(index)(a1,a2,a3,a4);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_ii(index,a1) {\n  var sp = stackSave();\n  try {\n    return getWasmTableEntry(index)(a1);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6) {\n  var sp = stackSave();\n  try {\n    return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iiiii(index,a1,a2,a3,a4) {\n  var sp = stackSave();\n  try {\n    return getWasmTableEntry(index)(a1,a2,a3,a4);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iiiiii(index,a1,a2,a3,a4,a5) {\n  var sp = stackSave();\n  try {\n    return getWasmTableEntry(index)(a1,a2,a3,a4,a5);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_vdiii(index,a1,a2,a3,a4) {\n  var sp = stackSave();\n  try {\n    getWasmTableEntry(index)(a1,a2,a3,a4);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_idiii(index,a1,a2,a3,a4) {\n  var sp = stackSave();\n  try {\n    return getWasmTableEntry(index)(a1,a2,a3,a4);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iij(index,a1,a2,a3) {\n  var sp = stackSave();\n  try {\n    return dynCall_iij(index,a1,a2,a3);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iijiii(index,a1,a2,a3,a4,a5,a6) {\n  var sp = stackSave();\n  try {\n    return dynCall_iijiii(index,a1,a2,a3,a4,a5,a6);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8) {\n  var sp = stackSave();\n  try {\n    return dynCall_iijjiii(index,a1,a2,a3,a4,a5,a6,a7,a8);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_j(index) {\n  var sp = stackSave();\n  try {\n    return dynCall_j(index);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iiji(index,a1,a2,a3,a4) {\n  var sp = stackSave();\n  try {\n    return dynCall_iiji(index,a1,a2,a3,a4);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_vjjiii(index,a1,a2,a3,a4,a5,a6,a7) {\n  var sp = stackSave();\n  try {\n    dynCall_vjjiii(index,a1,a2,a3,a4,a5,a6,a7);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_ijjiii(index,a1,a2,a3,a4,a5,a6,a7) {\n  var sp = stackSave();\n  try {\n    return dynCall_ijjiii(index,a1,a2,a3,a4,a5,a6,a7);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_vijj(index,a1,a2,a3,a4,a5) {\n  var sp = stackSave();\n  try {\n    dynCall_vijj(index,a1,a2,a3,a4,a5);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_iijj(index,a1,a2,a3,a4,a5) {\n  var sp = stackSave();\n  try {\n    return dynCall_iijj(index,a1,a2,a3,a4,a5);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\nfunction invoke_vij(index,a1,a2,a3) {\n  var sp = stackSave();\n  try {\n    dynCall_vij(index,a1,a2,a3);\n  } catch(e) {\n    stackRestore(sp);\n    if (e !== e+0) throw e;\n    _setThrew(1, 0);\n  }\n}\n\n\n\n\n// === Auto-generated postamble setup entry stuff ===\n\n\nvar unexportedRuntimeSymbols = [\n  'run',\n  'UTF8ArrayToString',\n  'UTF8ToString',\n  'stringToUTF8Array',\n  'stringToUTF8',\n  'lengthBytesUTF8',\n  'addOnPreRun',\n  'addOnInit',\n  'addOnPreMain',\n  'addOnExit',\n  'addOnPostRun',\n  'addRunDependency',\n  'removeRunDependency',\n  'FS_createFolder',\n  'FS_createPath',\n  'FS_createDataFile',\n  'FS_createPreloadedFile',\n  'FS_createLazyFile',\n  'FS_createLink',\n  'FS_createDevice',\n  'FS_unlink',\n  'getLEB',\n  'getFunctionTables',\n  'alignFunctionTables',\n  'registerFunctions',\n  'prettyPrint',\n  'getCompilerSetting',\n  'out',\n  'err',\n  'callMain',\n  'abort',\n  'keepRuntimeAlive',\n  'wasmMemory',\n  'stackAlloc',\n  'stackSave',\n  'stackRestore',\n  'getTempRet0',\n  'setTempRet0',\n  'writeStackCookie',\n  'checkStackCookie',\n  'ptrToString',\n  'zeroMemory',\n  'stringToNewUTF8',\n  'exitJS',\n  'getHeapMax',\n  'abortOnCannotGrowMemory',\n  'emscripten_realloc_buffer',\n  'ENV',\n  'ERRNO_CODES',\n  'ERRNO_MESSAGES',\n  'setErrNo',\n  'inetPton4',\n  'inetNtop4',\n  'inetPton6',\n  'inetNtop6',\n  'readSockaddr',\n  'writeSockaddr',\n  'DNS',\n  'getHostByName',\n  'Protocols',\n  'Sockets',\n  'getRandomDevice',\n  'warnOnce',\n  'traverseStack',\n  'UNWIND_CACHE',\n  'convertPCtoSourceLocation',\n  'readEmAsmArgsArray',\n  'readEmAsmArgs',\n  'runEmAsmFunction',\n  'runMainThreadEmAsm',\n  'jstoi_q',\n  'jstoi_s',\n  'getExecutableName',\n  'listenOnce',\n  'autoResumeAudioContext',\n  'dynCallLegacy',\n  'getDynCaller',\n  'dynCall',\n  'handleException',\n  'runtimeKeepalivePush',\n  'runtimeKeepalivePop',\n  'callUserCallback',\n  'maybeExit',\n  'safeSetTimeout',\n  'asmjsMangle',\n  'asyncLoad',\n  'alignMemory',\n  'mmapAlloc',\n  'handleAllocator',\n  'writeI53ToI64',\n  'writeI53ToI64Clamped',\n  'writeI53ToI64Signaling',\n  'writeI53ToU64Clamped',\n  'writeI53ToU64Signaling',\n  'readI53FromI64',\n  'readI53FromU64',\n  'convertI32PairToI53',\n  'convertI32PairToI53Checked',\n  'convertU32PairToI53',\n  'getCFunc',\n  'ccall',\n  'cwrap',\n  'uleb128Encode',\n  'sigToWasmTypes',\n  'generateFuncType',\n  'convertJsFunctionToWasm',\n  'freeTableIndexes',\n  'functionsInTableMap',\n  'getEmptyTableSlot',\n  'updateTableMap',\n  'addFunction',\n  'removeFunction',\n  'reallyNegative',\n  'unSign',\n  'strLen',\n  'reSign',\n  'formatString',\n  'setValue',\n  'getValue',\n  'PATH',\n  'PATH_FS',\n  'intArrayFromString',\n  'intArrayToString',\n  'AsciiToString',\n  'stringToAscii',\n  'UTF16Decoder',\n  'UTF16ToString',\n  'stringToUTF16',\n  'lengthBytesUTF16',\n  'UTF32ToString',\n  'stringToUTF32',\n  'lengthBytesUTF32',\n  'allocateUTF8',\n  'allocateUTF8OnStack',\n  'writeStringToMemory',\n  'writeArrayToMemory',\n  'writeAsciiToMemory',\n  'SYSCALLS',\n  'getSocketFromFD',\n  'getSocketAddress',\n  'JSEvents',\n  'registerKeyEventCallback',\n  'specialHTMLTargets',\n  'maybeCStringToJsString',\n  'findEventTarget',\n  'findCanvasEventTarget',\n  'getBoundingClientRect',\n  'fillMouseEventData',\n  'registerMouseEventCallback',\n  'registerWheelEventCallback',\n  'registerUiEventCallback',\n  'registerFocusEventCallback',\n  'fillDeviceOrientationEventData',\n  'registerDeviceOrientationEventCallback',\n  'fillDeviceMotionEventData',\n  'registerDeviceMotionEventCallback',\n  'screenOrientation',\n  'fillOrientationChangeEventData',\n  'registerOrientationChangeEventCallback',\n  'fillFullscreenChangeEventData',\n  'registerFullscreenChangeEventCallback',\n  'JSEvents_requestFullscreen',\n  'JSEvents_resizeCanvasForFullscreen',\n  'registerRestoreOldStyle',\n  'hideEverythingExceptGivenElement',\n  'restoreHiddenElements',\n  'setLetterbox',\n  'currentFullscreenStrategy',\n  'restoreOldWindowedStyle',\n  'softFullscreenResizeWebGLRenderTarget',\n  'doRequestFullscreen',\n  'fillPointerlockChangeEventData',\n  'registerPointerlockChangeEventCallback',\n  'registerPointerlockErrorEventCallback',\n  'requestPointerLock',\n  'fillVisibilityChangeEventData',\n  'registerVisibilityChangeEventCallback',\n  'registerTouchEventCallback',\n  'fillGamepadEventData',\n  'registerGamepadEventCallback',\n  'registerBeforeUnloadEventCallback',\n  'fillBatteryEventData',\n  'battery',\n  'registerBatteryEventCallback',\n  'setCanvasElementSize',\n  'getCanvasElementSize',\n  'demangle',\n  'demangleAll',\n  'jsStackTrace',\n  'stackTrace',\n  'ExitStatus',\n  'getEnvStrings',\n  'checkWasiClock',\n  'flush_NO_FILESYSTEM',\n  'dlopenMissingError',\n  'createDyncallWrapper',\n  'setImmediateWrapped',\n  'clearImmediateWrapped',\n  'polyfillSetImmediate',\n  'promiseMap',\n  'newNativePromise',\n  'getPromise',\n  'uncaughtExceptionCount',\n  'exceptionLast',\n  'exceptionCaught',\n  'ExceptionInfo',\n  'exception_addRef',\n  'exception_decRef',\n  'Browser',\n  'setMainLoop',\n  'wget',\n  'FS',\n  'MEMFS',\n  'TTY',\n  'PIPEFS',\n  'SOCKFS',\n  '_setNetworkCallback',\n  'tempFixedLengthArray',\n  'miniTempWebGLFloatBuffers',\n  'heapObjectForWebGLType',\n  'heapAccessShiftForWebGLHeap',\n  'GL',\n  'emscriptenWebGLGet',\n  'computeUnpackAlignedImageSize',\n  'emscriptenWebGLGetTexPixelData',\n  'emscriptenWebGLGetUniform',\n  'webglGetUniformLocation',\n  'webglPrepareUniformLocationsBeforeFirstUse',\n  'webglGetLeftBracePos',\n  'emscriptenWebGLGetVertexAttrib',\n  'writeGLArray',\n  'AL',\n  'SDL_unicode',\n  'SDL_ttfContext',\n  'SDL_audio',\n  'SDL',\n  'SDL_gfx',\n  'GLUT',\n  'EGL',\n  'GLFW_Window',\n  'GLFW',\n  'GLEW',\n  'IDBStore',\n  'runAndAbortIfError',\n  'ALLOC_NORMAL',\n  'ALLOC_STACK',\n  'allocate',\n];\nunexportedRuntimeSymbols.forEach(unexportedRuntimeSymbol);\nvar missingLibrarySymbols = [\n  'zeroMemory',\n  'stringToNewUTF8',\n  'emscripten_realloc_buffer',\n  'setErrNo',\n  'inetPton4',\n  'inetNtop4',\n  'inetPton6',\n  'inetNtop6',\n  'readSockaddr',\n  'writeSockaddr',\n  'getHostByName',\n  'getRandomDevice',\n  'convertPCtoSourceLocation',\n  'runMainThreadEmAsm',\n  'jstoi_q',\n  'jstoi_s',\n  'listenOnce',\n  'autoResumeAudioContext',\n  'dynCallLegacy',\n  'getDynCaller',\n  'dynCall',\n  'runtimeKeepalivePush',\n  'runtimeKeepalivePop',\n  'callUserCallback',\n  'maybeExit',\n  'safeSetTimeout',\n  'asmjsMangle',\n  'asyncLoad',\n  'alignMemory',\n  'mmapAlloc',\n  'handleAllocator',\n  'writeI53ToI64',\n  'writeI53ToI64Clamped',\n  'writeI53ToI64Signaling',\n  'writeI53ToU64Clamped',\n  'writeI53ToU64Signaling',\n  'readI53FromI64',\n  'readI53FromU64',\n  'getCFunc',\n  'ccall',\n  'cwrap',\n  'uleb128Encode',\n  'sigToWasmTypes',\n  'generateFuncType',\n  'convertJsFunctionToWasm',\n  'getEmptyTableSlot',\n  'updateTableMap',\n  'addFunction',\n  'removeFunction',\n  'intArrayToString',\n  'AsciiToString',\n  'stringToAscii',\n  'UTF16ToString',\n  'stringToUTF16',\n  'lengthBytesUTF16',\n  'UTF32ToString',\n  'stringToUTF32',\n  'lengthBytesUTF32',\n  'allocateUTF8',\n  'allocateUTF8OnStack',\n  'writeStringToMemory',\n  'getSocketFromFD',\n  'getSocketAddress',\n  'registerKeyEventCallback',\n  'maybeCStringToJsString',\n  'findEventTarget',\n  'findCanvasEventTarget',\n  'getBoundingClientRect',\n  'fillMouseEventData',\n  'registerMouseEventCallback',\n  'registerWheelEventCallback',\n  'registerUiEventCallback',\n  'registerFocusEventCallback',\n  'fillDeviceOrientationEventData',\n  'registerDeviceOrientationEventCallback',\n  'fillDeviceMotionEventData',\n  'registerDeviceMotionEventCallback',\n  'screenOrientation',\n  'fillOrientationChangeEventData',\n  'registerOrientationChangeEventCallback',\n  'fillFullscreenChangeEventData',\n  'registerFullscreenChangeEventCallback',\n  'JSEvents_requestFullscreen',\n  'JSEvents_resizeCanvasForFullscreen',\n  'registerRestoreOldStyle',\n  'hideEverythingExceptGivenElement',\n  'restoreHiddenElements',\n  'setLetterbox',\n  'softFullscreenResizeWebGLRenderTarget',\n  'doRequestFullscreen',\n  'fillPointerlockChangeEventData',\n  'registerPointerlockChangeEventCallback',\n  'registerPointerlockErrorEventCallback',\n  'requestPointerLock',\n  'fillVisibilityChangeEventData',\n  'registerVisibilityChangeEventCallback',\n  'registerTouchEventCallback',\n  'fillGamepadEventData',\n  'registerGamepadEventCallback',\n  'registerBeforeUnloadEventCallback',\n  'fillBatteryEventData',\n  'battery',\n  'registerBatteryEventCallback',\n  'setCanvasElementSize',\n  'getCanvasElementSize',\n  'demangle',\n  'demangleAll',\n  'stackTrace',\n  'checkWasiClock',\n  'createDyncallWrapper',\n  'setImmediateWrapped',\n  'clearImmediateWrapped',\n  'polyfillSetImmediate',\n  'newNativePromise',\n  'getPromise',\n  'setMainLoop',\n  '_setNetworkCallback',\n  'heapObjectForWebGLType',\n  'heapAccessShiftForWebGLHeap',\n  'emscriptenWebGLGet',\n  'computeUnpackAlignedImageSize',\n  'emscriptenWebGLGetTexPixelData',\n  'emscriptenWebGLGetUniform',\n  'webglGetUniformLocation',\n  'webglPrepareUniformLocationsBeforeFirstUse',\n  'webglGetLeftBracePos',\n  'emscriptenWebGLGetVertexAttrib',\n  'writeGLArray',\n  'SDL_unicode',\n  'SDL_ttfContext',\n  'SDL_audio',\n  'GLFW_Window',\n  'runAndAbortIfError',\n  'ALLOC_NORMAL',\n  'ALLOC_STACK',\n  'allocate',\n];\nmissingLibrarySymbols.forEach(missingLibrarySymbol)\n\n\nvar calledRun;\n\ndependenciesFulfilled = function runCaller() {\n  // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)\n  if (!calledRun) run();\n  if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled\n};\n\nfunction callMain(args) {\n  assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module[\"onRuntimeInitialized\"])');\n  assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called');\n\n  var entryFunction = Module['_main'];\n\n  var argc = 0;\n  var argv = 0;\n\n  try {\n\n    var ret = entryFunction(argc, argv);\n\n    // In PROXY_TO_PTHREAD builds, we should never exit the runtime below, as\n    // execution is asynchronously handed off to a pthread.\n    // if we're not running an evented main loop, it's time to exit\n    exitJS(ret, /* implicit = */ true);\n    return ret;\n  }\n  catch (e) {\n    return handleException(e);\n  }\n}\n\nfunction stackCheckInit() {\n  // This is normally called automatically during __wasm_call_ctors but need to\n  // get these values before even running any of the ctors so we call it redundantly\n  // here.\n  _emscripten_stack_init();\n  // TODO(sbc): Move writeStackCookie to native to to avoid this.\n  writeStackCookie();\n}\n\n/** @type {function(Array=)} */\nfunction run(args) {\n  args = args || arguments_;\n\n  if (runDependencies > 0) {\n    return;\n  }\n\n    stackCheckInit();\n\n  preRun();\n\n  // a preRun added a dependency, run will be called later\n  if (runDependencies > 0) {\n    return;\n  }\n\n  function doRun() {\n    // run may have just been called through dependencies being fulfilled just in this very frame,\n    // or while the async setStatus time below was happening\n    if (calledRun) return;\n    calledRun = true;\n    Module['calledRun'] = true;\n\n    if (ABORT) return;\n\n    initRuntime();\n\n    preMain();\n\n    if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();\n\n    if (shouldRunNow) callMain(args);\n\n    postRun();\n  }\n\n  if (Module['setStatus']) {\n    Module['setStatus']('Running...');\n    setTimeout(function() {\n      setTimeout(function() {\n        Module['setStatus']('');\n      }, 1);\n      doRun();\n    }, 1);\n  } else\n  {\n    doRun();\n  }\n  checkStackCookie();\n}\n\nfunction checkUnflushedContent() {\n  // Compiler settings do not allow exiting the runtime, so flushing\n  // the streams is not possible. but in ASSERTIONS mode we check\n  // if there was something to flush, and if so tell the user they\n  // should request that the runtime be exitable.\n  // Normally we would not even include flush() at all, but in ASSERTIONS\n  // builds we do so just for this check, and here we see if there is any\n  // content to flush, that is, we check if there would have been\n  // something a non-ASSERTIONS build would have not seen.\n  // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0\n  // mode (which has its own special function for this; otherwise, all\n  // the code is inside libc)\n  var oldOut = out;\n  var oldErr = err;\n  var has = false;\n  out = err = (x) => {\n    has = true;\n  }\n  try { // it doesn't matter if it fails\n    flush_NO_FILESYSTEM();\n  } catch(e) {}\n  out = oldOut;\n  err = oldErr;\n  if (has) {\n    warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline when you printf etc.');\n    warnOnce('(this may also be due to not including full filesystem support - try building with -sFORCE_FILESYSTEM)');\n  }\n}\n\nif (Module['preInit']) {\n  if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];\n  while (Module['preInit'].length > 0) {\n    Module['preInit'].pop()();\n  }\n}\n\n// shouldRunNow refers to calling main(), not run().\nvar shouldRunNow = true;\n\nif (Module['noInitialRun']) shouldRunNow = false;\n\nrun();\n\n\n\n"
  }
]